jishushell 0.4.24 → 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/INSTALL-NOTICE +11 -0
- package/apps/anythingllm-container.yaml +287 -0
- package/apps/browserless-chromium-container.yaml +90 -0
- package/apps/filebrowser-container.yaml +163 -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 +38 -1
- package/apps/openclaw-container.yaml +45 -2
- package/apps/openclaw-with-ollama-container.yaml +11 -2
- package/apps/openclaw-with-searxng-container.yaml +26 -2
- package/apps/openwebui-container.yaml +45 -1
- package/apps/playwright-container.yaml +7 -1
- package/apps/searxng-container.yaml +58 -7
- package/apps/weknora-container.yaml +471 -0
- 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/config.d.ts +19 -0
- package/dist/config.js +99 -1
- package/dist/config.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/install.js +3 -3
- package/dist/install.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 +5 -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 +826 -17
- 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 +24 -35
- package/dist/routes/llm.js.map +1 -1
- package/dist/routes/setup.js +10 -10
- 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.d.ts +9 -0
- package/dist/server.js +751 -20
- 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-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 +25 -1
- package/dist/services/app/app-manager.js +829 -150
- 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 +7 -4
- 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/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/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/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 +91 -0
- package/dist/services/connection-apply.js +475 -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 +39 -0
- package/dist/services/connection-transactor.js +351 -0
- package/dist/services/connection-transactor.js.map +1 -0
- 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.d.ts +13 -0
- package/dist/services/instance-manager.js +138 -46
- 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 +24 -9
- 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 +428 -35
- 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 +4 -3
- 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 +219 -6
- 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-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 +177 -0
- package/dist/services/runtime/adapters/openclaw.js +1171 -11
- 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/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 +46 -0
- package/dist/services/setup-manager.js +99 -24
- 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/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 +231 -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/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-json.js +55 -22
- package/dist/utils/safe-json.js.map +1 -1
- 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 +323 -27
- package/install/jishu-uninstall.sh +353 -20
- package/package.json +18 -1
- package/public/assets/Dashboard-BdWPtroF.js +1 -0
- package/public/assets/{HermesChatPanel-mFSureyc.js → HermesChatPanel-B_2HlVBQ.js} +1 -1
- package/public/assets/HermesConfigForm-DVlhg3WV.js +4 -0
- package/public/assets/{InitPassword-CVA8wQA6.js → InitPassword-D7glTExX.js} +1 -1
- package/public/assets/InstanceDetail-CxSy2cpe.js +92 -0
- package/public/assets/{Login-BWsZH2mu.js → Login-Cfr5c2sv.js} +1 -1
- package/public/assets/NewInstance-BIYDmJis.js +1 -0
- package/public/assets/ProviderRecommendations-BuRnvRcI.js +1 -0
- package/public/assets/Settings-Cc-tYBil.js +1 -0
- package/public/assets/Setup-lGZEk5jq.js +1 -0
- package/public/assets/{WeixinLoginPanel-CnjR8xMu.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/providers-DtNXh9JD.js +1 -0
- package/public/assets/registry-BWnkJgZ1.js +2 -0
- 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 +457 -0
- package/scripts/check-i18n.mjs +154 -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/run.sh +4 -4
- 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-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,27 +2,274 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
JISHU_SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
-
# shellcheck source=jishu-install.sh
|
|
6
|
-
source "${JISHU_SCRIPT_DIR}/jishu-install.sh"
|
|
7
5
|
|
|
6
|
+
_get_user_home() {
|
|
7
|
+
local user="$1"
|
|
8
|
+
local user_home=""
|
|
9
|
+
|
|
10
|
+
if [[ -z "$user" ]]; then
|
|
11
|
+
return 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
if command -v getent >/dev/null 2>&1; then
|
|
15
|
+
user_home="$(getent passwd "$user" 2>/dev/null | cut -d: -f6 || true)"
|
|
16
|
+
elif command -v dscl >/dev/null 2>&1; then
|
|
17
|
+
user_home="$(dscl . -read "/Users/${user}" NFSHomeDirectory 2>/dev/null | awk '/NFSHomeDirectory:/{print $2; exit}')"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [[ -z "$user_home" ]]; then
|
|
21
|
+
user_home="$(eval "printf '%s' ~${user}" 2>/dev/null || true)"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
[[ -n "$user_home" ]] && printf '%s' "$user_home"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if [[ $EUID -eq 0 && -n "${SUDO_USER:-}" && "${SUDO_USER}" != "root" ]]; then
|
|
28
|
+
REAL_USER="${SUDO_USER}"
|
|
29
|
+
REAL_HOME="$(_get_user_home "${SUDO_USER}")"
|
|
30
|
+
else
|
|
31
|
+
REAL_USER="$(id -un)"
|
|
32
|
+
REAL_HOME="${HOME}"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
[[ -z "${REAL_HOME}" ]] && REAL_HOME="${HOME}"
|
|
36
|
+
USER_HOME="${REAL_HOME}"
|
|
37
|
+
JISHUSHELL_HOME="${JISHUSHELL_HOME:-${USER_HOME}/.jishushell}"
|
|
38
|
+
_COLIMA_HOME="${JISHUSHELL_HOME}/colima"
|
|
39
|
+
_COLIMA_PROFILE="jishushell"
|
|
40
|
+
|
|
41
|
+
BOLD='\033[1m'
|
|
42
|
+
ACCENT='\033[38;2;66;135;245m'
|
|
43
|
+
INFO='\033[38;2;136;146;176m'
|
|
44
|
+
SUCCESS='\033[38;2;0;229;204m'
|
|
45
|
+
WARN='\033[38;2;255;176;32m'
|
|
46
|
+
ERROR='\033[38;2;230;57;70m'
|
|
47
|
+
MUTED='\033[38;2;90;100;128m'
|
|
48
|
+
NC='\033[0m'
|
|
49
|
+
|
|
50
|
+
DRY_RUN="${DRY_RUN:-0}"
|
|
8
51
|
DO_DOCKER=0
|
|
9
52
|
DO_NOMAD=0
|
|
53
|
+
DO_XCODE_CLT=0
|
|
54
|
+
DO_BREW=0
|
|
10
55
|
AUTO_YES=0
|
|
56
|
+
SUDO=""
|
|
57
|
+
PKG_MANAGER="none"
|
|
58
|
+
OS=""
|
|
59
|
+
OS_ID=""
|
|
60
|
+
OS_VERSION=""
|
|
61
|
+
OS_NAME=""
|
|
62
|
+
|
|
63
|
+
ui_info() {
|
|
64
|
+
echo -e "${MUTED}·${NC} $*"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
ui_success() {
|
|
68
|
+
echo -e "${SUCCESS}✓${NC} $*"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
ui_warn() {
|
|
72
|
+
echo -e "${WARN}!${NC} $*"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
ui_error() {
|
|
76
|
+
echo -e "${ERROR}✗${NC} $*" >&2
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
ui_section() {
|
|
80
|
+
echo -e "\n${ACCENT}${BOLD}── $* ──${NC}"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
confirm() {
|
|
84
|
+
local prompt="$1"
|
|
85
|
+
|
|
86
|
+
if [[ "${NO_PROMPT:-0}" == "1" ]]; then
|
|
87
|
+
ui_info "$prompt → auto-confirmed (NO_PROMPT=1)"
|
|
88
|
+
return 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if [[ "${AUTO_YES:-0}" == "1" ]]; then
|
|
92
|
+
ui_info "$prompt → auto-confirmed (--yes)"
|
|
93
|
+
return 0
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
local answer answer_lc
|
|
97
|
+
read -r -p "$(echo -e "${WARN} ${prompt} [y/N]: ${NC}")" answer </dev/tty || answer="n"
|
|
98
|
+
answer_lc="$(echo "$answer" | tr '[:upper:]' '[:lower:]')"
|
|
99
|
+
case "$answer_lc" in
|
|
100
|
+
y|yes) return 0 ;;
|
|
101
|
+
*) return 1 ;;
|
|
102
|
+
esac
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_run_as_real_user() {
|
|
106
|
+
if [[ $EUID -eq 0 && -n "${REAL_USER:-}" && "${REAL_USER}" != "root" ]]; then
|
|
107
|
+
sudo -u "${REAL_USER}" -H env HOME="${USER_HOME}" "$@"
|
|
108
|
+
return $?
|
|
109
|
+
fi
|
|
110
|
+
"$@"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_load_homebrew_shellenv() {
|
|
114
|
+
local brew_bin=""
|
|
115
|
+
|
|
116
|
+
if command -v brew >/dev/null 2>&1; then
|
|
117
|
+
brew_bin="$(command -v brew)"
|
|
118
|
+
elif [[ -x "/opt/homebrew/bin/brew" ]]; then
|
|
119
|
+
brew_bin="/opt/homebrew/bin/brew"
|
|
120
|
+
elif [[ -x "/usr/local/bin/brew" ]]; then
|
|
121
|
+
brew_bin="/usr/local/bin/brew"
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
if [[ -z "$brew_bin" ]]; then
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
eval "$(${brew_bin} shellenv 2>/dev/null)"
|
|
129
|
+
command -v brew >/dev/null 2>&1
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
detect_os() {
|
|
133
|
+
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
134
|
+
OS="macos"
|
|
135
|
+
OS_ID="macos"
|
|
136
|
+
OS_VERSION="$(sw_vers -productVersion 2>/dev/null || echo "unknown")"
|
|
137
|
+
OS_NAME="macOS ${OS_VERSION}"
|
|
138
|
+
if _load_homebrew_shellenv; then
|
|
139
|
+
PKG_MANAGER="brew"
|
|
140
|
+
else
|
|
141
|
+
PKG_MANAGER="none"
|
|
142
|
+
fi
|
|
143
|
+
ui_success "OS: ${OS_NAME}"
|
|
144
|
+
return 0
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
if [[ ! -f /etc/os-release ]]; then
|
|
148
|
+
ui_error "Cannot detect OS: /etc/os-release not found"
|
|
149
|
+
ui_error "This uninstaller supports Linux and macOS"
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# shellcheck source=/dev/null
|
|
154
|
+
. /etc/os-release
|
|
155
|
+
|
|
156
|
+
OS="linux"
|
|
157
|
+
OS_ID="${ID:-unknown}"
|
|
158
|
+
OS_VERSION="${VERSION_ID:-unknown}"
|
|
159
|
+
OS_NAME="${PRETTY_NAME:-$OS_ID $OS_VERSION}"
|
|
160
|
+
|
|
161
|
+
case "$OS_ID" in
|
|
162
|
+
ubuntu|debian|linuxmint|pop)
|
|
163
|
+
PKG_MANAGER="apt"
|
|
164
|
+
;;
|
|
165
|
+
centos|rhel|rocky|almalinux|fedora|amzn)
|
|
166
|
+
if command -v dnf >/dev/null 2>&1; then
|
|
167
|
+
PKG_MANAGER="dnf"
|
|
168
|
+
else
|
|
169
|
+
PKG_MANAGER="yum"
|
|
170
|
+
fi
|
|
171
|
+
;;
|
|
172
|
+
*)
|
|
173
|
+
if command -v apt-get >/dev/null 2>&1; then
|
|
174
|
+
PKG_MANAGER="apt"
|
|
175
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
176
|
+
PKG_MANAGER="dnf"
|
|
177
|
+
elif command -v yum >/dev/null 2>&1; then
|
|
178
|
+
PKG_MANAGER="yum"
|
|
179
|
+
fi
|
|
180
|
+
;;
|
|
181
|
+
esac
|
|
182
|
+
|
|
183
|
+
ui_success "OS: ${OS_NAME} (package manager: ${PKG_MANAGER})"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
check_sudo() {
|
|
187
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
188
|
+
if [[ $EUID -eq 0 ]]; then
|
|
189
|
+
SUDO=""
|
|
190
|
+
else
|
|
191
|
+
SUDO="sudo"
|
|
192
|
+
fi
|
|
193
|
+
return 0
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
if [[ $EUID -eq 0 ]]; then
|
|
197
|
+
SUDO=""
|
|
198
|
+
return 0
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
if ! command -v sudo >/dev/null 2>&1; then
|
|
202
|
+
ui_error "Not running as root and sudo is not installed. Re-run as root."
|
|
203
|
+
exit 1
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
if ! sudo -n true 2>/dev/null; then
|
|
207
|
+
ui_info "Some steps require sudo — you may be prompted for your password."
|
|
208
|
+
if [[ ! -t 0 || ! -t 1 ]]; then
|
|
209
|
+
ui_error "Failed to obtain sudo privileges (no interactive TTY available)"
|
|
210
|
+
exit 1
|
|
211
|
+
fi
|
|
212
|
+
if ! sudo -v; then
|
|
213
|
+
ui_error "Failed to obtain sudo privileges"
|
|
214
|
+
exit 1
|
|
215
|
+
fi
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
SUDO="sudo"
|
|
219
|
+
ui_success "sudo privileges confirmed"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
run_sudo() {
|
|
223
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
224
|
+
ui_info "[dry-run] ${SUDO:+sudo }$*"
|
|
225
|
+
return 0
|
|
226
|
+
fi
|
|
227
|
+
${SUDO} "$@"
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
wait_for_apt_lock() {
|
|
231
|
+
if [[ "${PKG_MANAGER:-}" != "apt" ]]; then
|
|
232
|
+
return 0
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
local max_wait=60
|
|
236
|
+
local waited=0
|
|
237
|
+
|
|
238
|
+
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || \
|
|
239
|
+
fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do
|
|
240
|
+
if [[ $waited -eq 0 ]]; then
|
|
241
|
+
ui_info "Waiting for apt lock to be released..."
|
|
242
|
+
fi
|
|
243
|
+
sleep 2
|
|
244
|
+
waited=$((waited + 2))
|
|
245
|
+
if [[ $waited -ge $max_wait ]]; then
|
|
246
|
+
ui_error "Timed out waiting for apt lock (${max_wait}s). Check for other running package managers."
|
|
247
|
+
exit 1
|
|
248
|
+
fi
|
|
249
|
+
done
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
_colima() {
|
|
253
|
+
COLIMA_HOME="${_COLIMA_HOME}" command colima "$@"
|
|
254
|
+
}
|
|
11
255
|
|
|
12
256
|
# ─── Argument parsing ─────────────────────────────────────────────────────────
|
|
13
257
|
usage() {
|
|
14
258
|
cat <<EOF
|
|
15
259
|
Usage: bash jishu-uninstall.sh [options]
|
|
16
260
|
|
|
17
|
-
|
|
18
|
-
|
|
261
|
+
Run without options to remove only JishuShell-owned files and runtime data:
|
|
262
|
+
stop JishuShell services, remove the jishushell package, and optionally
|
|
263
|
+
delete the data directory (~/.jishushell).
|
|
19
264
|
|
|
20
|
-
|
|
21
|
-
|
|
265
|
+
System-installed tools (colima, docker, nomad, Homebrew, Xcode Command Line
|
|
266
|
+
Tools, Node.js) are never removed unless you explicitly pass extra flags.
|
|
22
267
|
|
|
23
268
|
Options:
|
|
24
269
|
--docker Also uninstall Docker/Colima system packages (brew/apt/dnf)
|
|
25
270
|
--nomad Also uninstall Nomad system package (brew/apt/dnf)
|
|
271
|
+
--xcode-clt Also delete macOS Xcode Command Line Tools
|
|
272
|
+
--brew Also run the official Homebrew uninstall script (macOS)
|
|
26
273
|
--all Full uninstall: default cleanup + --docker + --nomad + --yes
|
|
27
274
|
--dry-run Print the removal plan only, do not execute anything
|
|
28
275
|
--yes, -y Skip all confirmation prompts (auto-yes)
|
|
@@ -36,6 +283,8 @@ parse_args() {
|
|
|
36
283
|
case "$1" in
|
|
37
284
|
--docker) DO_DOCKER=1 ;;
|
|
38
285
|
--nomad) DO_NOMAD=1 ;;
|
|
286
|
+
--xcode-clt) DO_XCODE_CLT=1 ;;
|
|
287
|
+
--brew) DO_BREW=1 ;;
|
|
39
288
|
--all) DO_DOCKER=1; DO_NOMAD=1; AUTO_YES=1 ;;
|
|
40
289
|
--dry-run) DRY_RUN=1 ;;
|
|
41
290
|
--yes|-y) AUTO_YES=1 ;;
|
|
@@ -99,8 +348,8 @@ stop_services() {
|
|
|
99
348
|
fi
|
|
100
349
|
|
|
101
350
|
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
102
|
-
local panel_plist="${
|
|
103
|
-
local nomad_plist="${
|
|
351
|
+
local panel_plist="${USER_HOME}/Library/LaunchAgents/com.jishushell.panel.plist"
|
|
352
|
+
local nomad_plist="${USER_HOME}/Library/LaunchAgents/com.jishushell.nomad.plist"
|
|
104
353
|
|
|
105
354
|
if launchctl list 2>/dev/null | grep -q "com.jishushell.panel"; then
|
|
106
355
|
ui_info "Stopping JishuShell panel..."
|
|
@@ -160,7 +409,7 @@ stop_services() {
|
|
|
160
409
|
local _cmd
|
|
161
410
|
_cmd="$(ps -p "$_pid" -o args= 2>/dev/null || true)"
|
|
162
411
|
# Only kill nomad agents that reference our config directory
|
|
163
|
-
if [[ "$_cmd" == *"${JISHUSHELL_HOME
|
|
412
|
+
if [[ "$_cmd" == *"${JISHUSHELL_HOME}"* ]]; then
|
|
164
413
|
kill "$_pid" 2>/dev/null || true
|
|
165
414
|
((_killed_nomad++)) || true
|
|
166
415
|
fi
|
|
@@ -173,7 +422,7 @@ stop_services() {
|
|
|
173
422
|
if kill -0 "$_pid" 2>/dev/null; then
|
|
174
423
|
local _cmd
|
|
175
424
|
_cmd="$(ps -p "$_pid" -o args= 2>/dev/null || true)"
|
|
176
|
-
if [[ "$_cmd" == *"${JISHUSHELL_HOME
|
|
425
|
+
if [[ "$_cmd" == *"${JISHUSHELL_HOME}"* ]]; then
|
|
177
426
|
kill -9 "$_pid" 2>/dev/null || true
|
|
178
427
|
fi
|
|
179
428
|
fi
|
|
@@ -211,7 +460,7 @@ stop_services() {
|
|
|
211
460
|
fi
|
|
212
461
|
|
|
213
462
|
# Clean leaked ~/.colima directory (Colima stat-guard artifact)
|
|
214
|
-
local default_colima_home="${
|
|
463
|
+
local default_colima_home="${USER_HOME}/.colima"
|
|
215
464
|
if [[ -d "$default_colima_home" ]]; then
|
|
216
465
|
local real_files
|
|
217
466
|
real_files="$(find "$default_colima_home" -type f 2>/dev/null | head -1 || true)"
|
|
@@ -226,7 +475,7 @@ stop_services() {
|
|
|
226
475
|
fi
|
|
227
476
|
fi
|
|
228
477
|
|
|
229
|
-
local wrapper="${
|
|
478
|
+
local wrapper="${JISHUSHELL_HOME}/bin/jishushell-panel-start"
|
|
230
479
|
if [[ -f "$wrapper" ]]; then
|
|
231
480
|
rm -f "$wrapper"
|
|
232
481
|
ui_success "Removed wrapper: ${wrapper}"
|
|
@@ -234,7 +483,7 @@ stop_services() {
|
|
|
234
483
|
|
|
235
484
|
# Clean JishuShell PATH entries from shell RC files.
|
|
236
485
|
local marker="# jishushell-bin-path"
|
|
237
|
-
local shell_configs=("$
|
|
486
|
+
local shell_configs=("${USER_HOME}/.bashrc" "${USER_HOME}/.bash_profile" "${USER_HOME}/.profile" "${USER_HOME}/.zshrc")
|
|
238
487
|
for cfg in "${shell_configs[@]}"; do
|
|
239
488
|
if [[ -f "$cfg" ]] && grep -qF "$marker" "$cfg" 2>/dev/null; then
|
|
240
489
|
ui_info "Cleaning JishuShell PATH from ${cfg}..."
|
|
@@ -255,7 +504,7 @@ stop_services() {
|
|
|
255
504
|
|
|
256
505
|
# ─── Delete ~/.jishushell data directory ──────────────────────────────────────
|
|
257
506
|
delete_data_dir() {
|
|
258
|
-
local jishu_home="${JISHUSHELL_HOME
|
|
507
|
+
local jishu_home="${JISHUSHELL_HOME}"
|
|
259
508
|
if [[ ! -d "$jishu_home" ]]; then
|
|
260
509
|
ui_info "Data directory does not exist: ${jishu_home}"
|
|
261
510
|
return 0
|
|
@@ -337,6 +586,86 @@ uninstall_colima() {
|
|
|
337
586
|
fi
|
|
338
587
|
}
|
|
339
588
|
|
|
589
|
+
# ─── macOS Xcode Command Line Tools (--xcode-clt flag) ───────────────────────
|
|
590
|
+
uninstall_xcode_clt() {
|
|
591
|
+
ui_section "Removing Xcode Command Line Tools"
|
|
592
|
+
|
|
593
|
+
if [[ "$OS" != "macos" ]]; then
|
|
594
|
+
ui_info "Xcode Command Line Tools removal is only supported on macOS"
|
|
595
|
+
return 0
|
|
596
|
+
fi
|
|
597
|
+
|
|
598
|
+
if [[ ! -d /Library/Developer/CommandLineTools ]]; then
|
|
599
|
+
ui_info "Xcode Command Line Tools are not installed, skipping"
|
|
600
|
+
return 0
|
|
601
|
+
fi
|
|
602
|
+
|
|
603
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
604
|
+
ui_info "[dry-run] Would: sudo rm -rf /Library/Developer/CommandLineTools"
|
|
605
|
+
return 0
|
|
606
|
+
fi
|
|
607
|
+
|
|
608
|
+
ui_warn "This will delete /Library/Developer/CommandLineTools from this Mac."
|
|
609
|
+
if ! confirm "Delete Xcode Command Line Tools?"; then
|
|
610
|
+
ui_info "Xcode Command Line Tools kept"
|
|
611
|
+
return 0
|
|
612
|
+
fi
|
|
613
|
+
|
|
614
|
+
run_sudo rm -rf /Library/Developer/CommandLineTools
|
|
615
|
+
if [[ ! -d /Library/Developer/CommandLineTools ]]; then
|
|
616
|
+
ui_success "Xcode Command Line Tools removed"
|
|
617
|
+
return 0
|
|
618
|
+
fi
|
|
619
|
+
|
|
620
|
+
ui_warn "Could not fully remove /Library/Developer/CommandLineTools"
|
|
621
|
+
return 1
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
# ─── Homebrew uninstall (--brew flag) ────────────────────────────────────────
|
|
625
|
+
uninstall_homebrew() {
|
|
626
|
+
ui_section "Removing Homebrew"
|
|
627
|
+
|
|
628
|
+
if [[ "$OS" != "macos" ]]; then
|
|
629
|
+
ui_info "Homebrew removal is only supported on macOS"
|
|
630
|
+
return 0
|
|
631
|
+
fi
|
|
632
|
+
|
|
633
|
+
if [[ ! -x /opt/homebrew/bin/brew && ! -x /usr/local/bin/brew && ! -d /opt/homebrew && ! -d /usr/local/Homebrew ]]; then
|
|
634
|
+
ui_info "Homebrew not found — skipping"
|
|
635
|
+
return 0
|
|
636
|
+
fi
|
|
637
|
+
|
|
638
|
+
if [[ "$DRY_RUN" == "1" ]]; then
|
|
639
|
+
ui_info '[dry-run] Would: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"'
|
|
640
|
+
return 0
|
|
641
|
+
fi
|
|
642
|
+
|
|
643
|
+
ui_warn "This will run the official Homebrew uninstall script and may remove all Homebrew packages on this Mac."
|
|
644
|
+
if ! confirm "Run Homebrew uninstall script?"; then
|
|
645
|
+
ui_info "Homebrew kept"
|
|
646
|
+
return 0
|
|
647
|
+
fi
|
|
648
|
+
|
|
649
|
+
local uninstall_script=""
|
|
650
|
+
if ! uninstall_script="$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"; then
|
|
651
|
+
ui_warn "Failed to download the Homebrew uninstall script"
|
|
652
|
+
return 1
|
|
653
|
+
fi
|
|
654
|
+
|
|
655
|
+
if ! _run_as_real_user /bin/bash -c "$uninstall_script"; then
|
|
656
|
+
ui_warn "Homebrew uninstall script failed"
|
|
657
|
+
return 1
|
|
658
|
+
fi
|
|
659
|
+
|
|
660
|
+
hash -r 2>/dev/null || true
|
|
661
|
+
if [[ -x /opt/homebrew/bin/brew || -x /usr/local/bin/brew || -d /opt/homebrew || -d /usr/local/Homebrew ]]; then
|
|
662
|
+
ui_warn "Homebrew may still be present after uninstall"
|
|
663
|
+
return 1
|
|
664
|
+
fi
|
|
665
|
+
|
|
666
|
+
ui_success "Homebrew removed"
|
|
667
|
+
}
|
|
668
|
+
|
|
340
669
|
# ─── Docker (Linux, --docker flag) ───────────────────────────────────────────
|
|
341
670
|
uninstall_docker() {
|
|
342
671
|
ui_section "Removing Docker"
|
|
@@ -362,7 +691,7 @@ uninstall_docker() {
|
|
|
362
691
|
fi
|
|
363
692
|
ui_info "[dry-run] Would groupdel docker"
|
|
364
693
|
ui_info "[dry-run] Would remove /var/lib/docker /var/lib/containerd /etc/docker"
|
|
365
|
-
ui_info "[dry-run] Would remove
|
|
694
|
+
ui_info "[dry-run] Would remove ${USER_HOME}/.docker"
|
|
366
695
|
ui_info "[dry-run] Would: systemctl daemon-reload"
|
|
367
696
|
return 0
|
|
368
697
|
fi
|
|
@@ -483,12 +812,12 @@ uninstall_docker() {
|
|
|
483
812
|
done
|
|
484
813
|
|
|
485
814
|
# Remove user Docker config directory (~/.docker contains credentials and config)
|
|
486
|
-
if [[ -d "${
|
|
815
|
+
if [[ -d "${USER_HOME}/.docker" ]]; then
|
|
487
816
|
if confirm "Delete user Docker config directory (~/.docker)?"; then
|
|
488
|
-
rm -rf "${
|
|
489
|
-
ui_success "Removed: ${
|
|
817
|
+
rm -rf "${USER_HOME}/.docker" 2>/dev/null || true
|
|
818
|
+
ui_success "Removed: ${USER_HOME}/.docker"
|
|
490
819
|
else
|
|
491
|
-
ui_info "Kept: ${
|
|
820
|
+
ui_info "Kept: ${USER_HOME}/.docker"
|
|
492
821
|
fi
|
|
493
822
|
fi
|
|
494
823
|
|
|
@@ -515,7 +844,7 @@ uninstall_nomad() {
|
|
|
515
844
|
|
|
516
845
|
local system_nomad
|
|
517
846
|
system_nomad="$(command -v nomad 2>/dev/null || true)"
|
|
518
|
-
local local_bin="${JISHUSHELL_HOME
|
|
847
|
+
local local_bin="${JISHUSHELL_HOME}/bin/nomad"
|
|
519
848
|
# Ignore if system PATH resolves to our local bin (that gets cleaned with ~/.jishushell)
|
|
520
849
|
[[ "$system_nomad" == "$local_bin" ]] && system_nomad=""
|
|
521
850
|
|
|
@@ -636,6 +965,8 @@ show_plan() {
|
|
|
636
965
|
echo -e " ${WARN}·${NC} Data directory (~/.jishushell) — will ask"
|
|
637
966
|
[[ $DO_DOCKER -eq 1 ]] && echo -e " ${WARN}·${NC} Uninstall Docker/Colima system packages (brew/apt/dnf)"
|
|
638
967
|
[[ $DO_NOMAD -eq 1 ]] && echo -e " ${WARN}·${NC} Uninstall Nomad system package (brew/apt/dnf)"
|
|
968
|
+
[[ $DO_BREW -eq 1 ]] && echo -e " ${WARN}·${NC} Run the official Homebrew uninstall script (macOS)"
|
|
969
|
+
[[ $DO_XCODE_CLT -eq 1 ]] && echo -e " ${WARN}·${NC} Delete /Library/Developer/CommandLineTools (macOS)"
|
|
639
970
|
if [[ "$DRY_RUN" == "1" ]]; then
|
|
640
971
|
echo ""
|
|
641
972
|
echo -e "${WARN} Dry-run mode: no changes will be made${NC}"
|
|
@@ -683,6 +1014,8 @@ main() {
|
|
|
683
1014
|
fi
|
|
684
1015
|
|
|
685
1016
|
[[ $DO_NOMAD -eq 1 ]] && { uninstall_nomad || uninstall_errors=1; }
|
|
1017
|
+
[[ $DO_BREW -eq 1 ]] && { uninstall_homebrew || uninstall_errors=1; }
|
|
1018
|
+
[[ $DO_XCODE_CLT -eq 1 ]] && { uninstall_xcode_clt || uninstall_errors=1; }
|
|
686
1019
|
|
|
687
1020
|
echo ""
|
|
688
1021
|
if [[ $uninstall_errors -eq 0 ]]; then
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jishushell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.15",
|
|
4
4
|
"description": "JishuShell - Multi-Agent Framework Management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"build": "npm install && tsc && cd frontend && npm install && npm run build",
|
|
24
24
|
"build:backend": "npm install && tsc",
|
|
25
25
|
"build:frontend": "cd frontend && npm install && npm run build",
|
|
26
|
+
"compile": "npm run compile:backend && npm --prefix frontend run build",
|
|
27
|
+
"compile:backend": "tsc",
|
|
28
|
+
"lint": "npx biome check .",
|
|
29
|
+
"lint:fix": "npx biome check --fix .",
|
|
26
30
|
"start": "node dist/cli.js serve",
|
|
27
31
|
"dev": "tsc --watch",
|
|
28
32
|
"test": "vitest run",
|
|
@@ -33,6 +37,11 @@
|
|
|
33
37
|
"test:watch": "vitest",
|
|
34
38
|
"test:coverage": "vitest run --coverage",
|
|
35
39
|
"test:ci": "npm run check:contracts && npm run build:backend && vitest run --coverage && cd frontend && npm install && npm run test",
|
|
40
|
+
"check:quarantine": "node scripts/check-quarantine-expiry.mjs",
|
|
41
|
+
"test:changed": "vitest run --changed",
|
|
42
|
+
"test:mutation": "stryker run",
|
|
43
|
+
"test:ci:backend": "vitest run --coverage --reporter=default --reporter=junit --outputFile.junit=test-results/backend-junit.xml",
|
|
44
|
+
"test:ci:frontend": "npm --prefix frontend run test -- --reporter=default --reporter=junit --outputFile.junit=test-results/frontend-junit.xml",
|
|
36
45
|
"test:ci:full": "npm run test:ci && vitest run --config vitest.e2e-real.config.ts",
|
|
37
46
|
"prepublishOnly": "npm run build && chmod +x dist/cli.js",
|
|
38
47
|
"postinstall": "bash install/post-install.sh",
|
|
@@ -40,6 +49,9 @@
|
|
|
40
49
|
"prepare": "git config core.hooksPath .githooks 2>/dev/null || true",
|
|
41
50
|
"build:pack": "npm run build && npm pack",
|
|
42
51
|
"check:contracts": "node --experimental-strip-types scripts/check-adapter-isolation.ts",
|
|
52
|
+
"check:i18n": "node scripts/check-i18n.mjs",
|
|
53
|
+
"check:app-spec": "node scripts/check-app-spec.mjs",
|
|
54
|
+
"check:new-file-tests": "node scripts/check-new-file-tests.mjs",
|
|
43
55
|
"version": "node -e \"const fs=require('fs'),v=JSON.parse(fs.readFileSync('./package.json','utf8')).version,fp='./frontend/package.json',p=JSON.parse(fs.readFileSync(fp,'utf8'));p.version=v;fs.writeFileSync(fp,JSON.stringify(p,null,2)+'\\n')\" && git add frontend/package.json"
|
|
44
56
|
},
|
|
45
57
|
"engines": {
|
|
@@ -62,12 +74,17 @@
|
|
|
62
74
|
"@fastify/static": "^8.1.0",
|
|
63
75
|
"@noble/hashes": "^2.0.1",
|
|
64
76
|
"bcryptjs": "^2.4.3",
|
|
77
|
+
"exifr": "^7.1.3",
|
|
65
78
|
"fastify": "^5.2.0",
|
|
66
79
|
"jsonwebtoken": "^9.0.2",
|
|
67
80
|
"systeminformation": "^5.23.0",
|
|
68
81
|
"yaml": "^2.8.3"
|
|
69
82
|
},
|
|
70
83
|
"devDependencies": {
|
|
84
|
+
"@biomejs/biome": "^2.4.14",
|
|
85
|
+
"@stryker-mutator/core": "^9.6.1",
|
|
86
|
+
"@stryker-mutator/typescript-checker": "^9.6.1",
|
|
87
|
+
"@stryker-mutator/vitest-runner": "^9.6.1",
|
|
71
88
|
"@types/bcryptjs": "^2.4.6",
|
|
72
89
|
"@types/jsonwebtoken": "^9.0.7",
|
|
73
90
|
"@types/node": "^22.19.15",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{k as W,j as e,L as K,l as $,m as A,n as L,o as I,q as T,t as E,v as M,w as R,x as U}from"./index-BZc5zH7u.js";import{r as u,u as D}from"./vendor-react-BWrEVJVb.js";import{u as P}from"./usePolling-CwwT9KrC.js";import{u as _}from"./vendor-i18n-y9V7Sfuu.js";function G(t){if(!t)return"-";const o=Math.floor(t/86400),l=Math.floor(t%86400/3600),a=Math.floor(t%3600/60);return o>0?`${o}d ${l}h`:l>0?`${l}h ${a}m`:`${a}m`}function q({status:t}){const{t:o}=_(),a={running:{cls:"bg-emerald-500/10 text-emerald-400 border border-emerald-500/20",labelKey:"status.running"},pending:{cls:"bg-amber-500/10 text-amber-400 border border-amber-500/20",labelKey:"status.starting"},failed:{cls:"bg-red-500/10 text-red-400 border border-red-500/20",labelKey:"status.failed"},dead:{cls:"bg-red-500/10 text-red-400 border border-red-500/20",labelKey:"status.crashed"}}[t]||{cls:"bg-[var(--card)] text-muted border border-[var(--border)]",labelKey:"status.stopped"};return e.jsx("span",{className:`inline-flex items-center text-xs px-2 py-0.5 rounded-full font-medium ${a.cls}`,children:o(a.labelKey)})}const O=[{key:"localInference",labelKey:"capability.localInference",cls:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20"},{key:"knowledgeBase",labelKey:"capability.knowledgeBase",cls:"bg-indigo-500/10 text-indigo-400 border-indigo-500/20"},{key:"files",labelKey:"capability.files",cls:"bg-amber-500/10 text-amber-400 border-amber-500/20"},{key:"search",labelKey:"capability.search",cls:"bg-sky-500/10 text-sky-400 border-sky-500/20"},{key:"browser",labelKey:"capability.browser",cls:"bg-violet-500/10 text-violet-400 border-violet-500/20"},{key:"aiWebUi",labelKey:"capability.aiWebUi",cls:"bg-cyan-500/10 text-cyan-400 border-cyan-500/20"},{key:"webUi",labelKey:"capability.webUi",cls:"bg-slate-500/10 text-muted border-[var(--border)]"}];function V(t){const o=new Set((Array.isArray(t==null?void 0:t.provides)?t.provides:[]).map(r=>String((r==null?void 0:r.capability)??"").toLowerCase()).filter(Boolean));if(o.has("llm-agent"))return[];const l=r=>{for(const m of o)if(r(m))return!0;return!1},a=new Set;return l(r=>r==="llm-ollama"||r==="ollama-api")&&a.add("localInference"),l(r=>r.startsWith("knowledge-")||r.includes("anythingllm")||r.includes("weknora"))&&a.add("knowledgeBase"),l(r=>r.startsWith("files-")||r.includes("filebrowser"))&&a.add("files"),l(r=>r==="search"||r.startsWith("search-"))&&a.add("search"),l(r=>r==="browser"||r.startsWith("browser-")||r.startsWith("web-browserless")||r.startsWith("playwright"))&&a.add("browser"),l(r=>r.includes("openwebui"))&&a.add("aiWebUi"),!a.size&&l(r=>r.startsWith("web-")||r.endsWith("-web")||r.endsWith("-dashboard"))&&a.add("webUi"),O.filter(r=>a.has(r.key))}function Q(){const{t}=_(["dashboard","common"]),[o,l]=u.useState([]),[a,r]=u.useState(null),[m,v]=u.useState(""),[j,w]=u.useState(""),[g,N]=u.useState(!1),f=D(),{showToast:b}=W(),h=()=>{I().then(s=>{l(s),w("")}).catch(s=>w(s.message||t("common:error.loadFailed"))),T().then(r).catch(()=>{})};P(h,1e4);const F=async()=>{if(window.confirm(t("engine.restartConfirm"))){N(!0);try{await E(),b(t("engine.restarted"),"success"),setTimeout(h,2e3)}catch(s){b(s.message||t("engine.restartFailed"),"error")}finally{N(!1)}}},y=async(s,n,x)=>{s.stopPropagation(),v(`${x}-${n}`);try{let i=null;n==="start"&&(i=await M(x)),n==="stop"&&(i=await R(x)),n==="restart"&&(i=await U(x)),b(t(`common:action.${n}Done`),"success");const d=i==null?void 0:i.port_allocation;d&&typeof d.from=="number"&&typeof d.to=="number"&&d.from!==d.to&&b(t("common:toast.portReallocated",{defaultValue:"端口 {{from}} 被占用,已自动切换到 {{to}}",from:d.from,to:d.to}),"info"),setTimeout(h,1e3)}catch(i){b(i.message||t("common:error.operationFailed"),"error")}finally{v("")}},S=o.filter(s=>{var n;return((n=s.service)==null?void 0:n.status)==="running"}).length,p=!!a&&a.disk.percent>90,B=a?[{label:t("stats.runningInstances"),value:`${S} / ${o.length}`,sub:a.nomad_running?t("stats.engineRunning"):t("stats.engineStopped"),subColor:a.nomad_running?"text-emerald-400":"text-red-400",icon:e.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,children:[e.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}),e.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),e.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]}),iconColor:"text-[#0066FF]",glowColor:"rgba(0,102,255,0.12)",accent:"border-l-2 border-l-[#0066FF]"},{label:t("stats.cpu"),value:`${a.cpu_percent}%`,sub:a.temperature?`${a.temperature}°C`:null,icon:e.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,children:[e.jsx("rect",{x:"4",y:"4",width:"16",height:"16",rx:"2"}),e.jsx("rect",{x:"9",y:"9",width:"6",height:"6"}),e.jsx("line",{x1:"9",y1:"2",x2:"9",y2:"4"}),e.jsx("line",{x1:"15",y1:"2",x2:"15",y2:"4"}),e.jsx("line",{x1:"9",y1:"20",x2:"9",y2:"22"}),e.jsx("line",{x1:"15",y1:"20",x2:"15",y2:"22"}),e.jsx("line",{x1:"20",y1:"9",x2:"22",y2:"9"}),e.jsx("line",{x1:"20",y1:"15",x2:"22",y2:"15"}),e.jsx("line",{x1:"2",y1:"9",x2:"4",y2:"9"}),e.jsx("line",{x1:"2",y1:"15",x2:"4",y2:"15"})]}),iconColor:"text-[#0066FF]",glowColor:"rgba(0,102,255,0.12)",accent:"border-l-2 border-l-[#0066FF]",warn:a.cpu_percent>90},{label:t("stats.memory"),value:`${a.memory.percent}%`,sub:`${a.memory.used_mb}MB / ${a.memory.total_mb}MB`,icon:e.jsx("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,children:e.jsx("path",{d:"M6 19v-8m4 8v-4m4 4v-6m4 6v-2"})}),iconColor:"text-[#00D4AA]",glowColor:"rgba(0,212,170,0.12)",accent:"border-l-2 border-l-[#00D4AA]"},{label:t("stats.disk"),value:`${a.disk.percent}%`,sub:`${a.disk.used_gb}GB / ${a.disk.total_gb}GB`,icon:e.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,children:[e.jsx("ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}),e.jsx("path",{d:"M3 5v14a9 3 0 0018 0V5"}),e.jsx("line",{x1:"12",y1:"8",x2:"12",y2:"22"})]}),iconColor:p?"text-red-400":"text-[#0066FF]",glowColor:p?"rgba(239,68,68,0.12)":"rgba(0,102,255,0.12)",accent:p?"border-l-2 border-l-red-400":"border-l-2 border-l-[#0066FF]",warn:p}]:[];return e.jsxs("div",{className:"p-4 2xl:px-6 2xl:py-3 max-w-5xl xl:max-w-6xl 2xl:max-w-none mx-auto",children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-base font-semibold text-foreground",children:t("title")}),e.jsx("p",{className:"text-xs text-muted mt-0.5",children:t("subtitle")})]}),e.jsx(K,{})]}),a&&e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-3 mb-4",children:B.map(s=>e.jsxs("div",{className:`bg-[var(--card)] border border-[var(--border)] rounded-lg p-3 relative overflow-hidden hover:border-[var(--border-hover)] hover:bg-[var(--card-hover)] transition-all duration-200 ${s.accent}`,children:[e.jsx("div",{className:"absolute top-0 right-0 w-16 h-16 rounded-full opacity-60 pointer-events-none",style:{background:`radial-gradient(circle, ${s.glowColor} 0%, transparent 70%)`}}),e.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[e.jsx("span",{className:"text-[11px] text-muted",children:s.label}),e.jsx("span",{className:`${s.iconColor} opacity-80`,children:s.icon})]}),e.jsx("div",{className:`text-lg font-semibold ${s.warn?"text-red-400":"text-foreground"}`,children:s.value}),s.sub&&e.jsx("div",{className:`text-[11px] mt-0.5 truncate ${s.subColor??"text-muted"}`,children:s.sub})]},s.label))}),e.jsxs("div",{className:"bg-[var(--card)] border border-[var(--border)] rounded-xl overflow-hidden",children:[e.jsxs("div",{className:"px-4 py-2.5 border-b border-[var(--border)] flex items-center justify-between",children:[e.jsx("h2",{className:"text-sm font-medium text-foreground",children:t("instances.title")}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>f("/instances/new"),className:"bg-[#0066FF] text-white px-3 py-1.5 rounded-md text-xs font-medium hover:bg-[#0066FF]/90 transition-all duration-200 shadow-[0_0_12px_rgba(0,102,255,0.3)]",children:t("instances.new")}),e.jsx("button",{onClick:()=>f("/instances/new?import=true"),className:"px-3 py-1.5 rounded-md text-xs font-medium text-muted border border-[var(--border)] bg-[var(--card)] hover:bg-[var(--card-hover)] hover:text-foreground transition-all duration-200",children:t("instances.import")}),e.jsxs("button",{onClick:F,disabled:g,title:t("instances.restartEngineTitle"),className:"flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-medium text-red-400 border border-red-500/20 bg-red-500/5 hover:bg-red-500/15 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200",children:[e.jsx($,{className:`w-3 h-3 ${g?"animate-spin":""}`}),t(g?"instances.restarting":"instances.restartEngine")]})]})]}),j?e.jsxs("div",{className:"text-center py-12 px-4",children:[e.jsx("p",{className:"text-sm text-red-400 mb-2",children:t("instances.loadError",{error:j})}),e.jsx("button",{onClick:h,className:"text-xs text-muted hover:text-foreground underline",children:t("common:action.retry")})]}):o.length===0?e.jsxs("div",{className:"text-center py-12 px-4",children:[e.jsx("div",{className:"text-muted opacity-40 mb-3",children:e.jsxs("svg",{className:"w-8 h-8 mx-auto",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1,strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}),e.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),e.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]})}),e.jsx("p",{className:"text-sm text-muted mb-1",children:t("instances.empty")}),e.jsx("p",{className:"text-xs text-muted opacity-60",children:t("instances.emptyHint")})]}):e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-xs text-muted border-b border-[var(--border)]",children:[e.jsx("th",{className:"text-left font-medium px-4 py-2",children:t("table.name")}),e.jsx("th",{className:"text-left font-medium px-4 py-2",children:t("table.status")}),e.jsx("th",{className:"text-left font-medium px-4 py-2 hidden sm:table-cell",children:t("table.uptime")}),e.jsx("th",{className:"text-left font-medium px-4 py-2 hidden md:table-cell",children:t("table.memory")}),e.jsx("th",{className:"text-left font-medium px-4 py-2 hidden lg:table-cell",children:t("table.localCapability")}),e.jsx("th",{className:"text-right font-medium px-4 py-2",children:t("table.actions")})]})}),e.jsx("tbody",{className:"divide-y divide-[var(--border)]",children:o.map(s=>{var d,k,C;const n=((d=s.service)==null?void 0:d.status)||"stopped",x=n==="running",i=V(s);return e.jsxs("tr",{className:"hover:bg-[var(--card-hover)] cursor-pointer transition-colors duration-150",onClick:()=>f(`/instances/${s.id}`),children:[e.jsxs("td",{className:"px-4 py-2.5",children:[e.jsx("div",{className:"font-medium text-foreground",children:s.name}),e.jsx("div",{className:"text-xs text-muted font-mono",children:s.id})]}),e.jsx("td",{className:"px-4 py-2.5",children:e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(q,{status:n}),((k=s.auto_backup)==null?void 0:k.enabled)&&e.jsx("span",{className:`text-xs leading-none ${s.auto_backup.last_backup_ok===!1?"text-red-400":"text-green-400"}`,title:s.auto_backup.last_backup_ok===!1?"Backup failed":"Backup OK",children:s.auto_backup.last_backup_ok===!1?"⚠":"●"})]})}),e.jsx("td",{className:"px-4 py-2.5 text-muted hidden sm:table-cell font-mono text-xs",children:x?G(s.service.uptime):"-"}),e.jsx("td",{className:"px-4 py-2.5 text-muted hidden md:table-cell font-mono text-xs",children:(C=s.service)!=null&&C.memory_mb?`${s.service.memory_mb} MB`:"-"}),e.jsx("td",{className:"px-4 py-2.5 hidden lg:table-cell",children:i.length?e.jsx("div",{className:"flex flex-wrap gap-1.5",children:i.map(c=>e.jsx("span",{className:`inline-flex items-center rounded-full border px-2 py-0.5 text-[11px] font-medium ${c.cls}`,children:t(c.labelKey)},c.key))}):e.jsx("span",{className:"text-muted text-xs",children:"-"})}),e.jsx("td",{className:"px-4 py-2.5 text-right",children:e.jsx("div",{className:"inline-flex items-center gap-1",children:x||n==="pending"?e.jsxs(e.Fragment,{children:[e.jsx("button",{title:t("common:action.restart"),onClick:c=>y(c,"restart",s.id),disabled:!!m,className:"p-1.5 rounded-md text-muted hover:text-foreground hover:bg-[var(--card-hover)] disabled:opacity-30 transition-colors duration-150",children:e.jsx($,{className:"w-3.5 h-3.5"})}),e.jsx("button",{title:t("common:action.stop"),onClick:c=>y(c,"stop",s.id),disabled:!!m,className:"p-1.5 rounded-md text-muted hover:text-red-400 hover:bg-red-500/10 disabled:opacity-30 transition-colors duration-150",children:e.jsx(A,{className:"w-3.5 h-3.5"})})]}):e.jsx("button",{title:t("common:action.start"),onClick:c=>y(c,"start",s.id),disabled:!!m,className:"p-1.5 rounded-md text-muted hover:text-emerald-400 hover:bg-emerald-500/10 disabled:opacity-30 transition-colors duration-150",children:e.jsx(L,{className:"w-3.5 h-3.5"})})})})]},s.id)})})]})]})]})}export{Q as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as r,
|
|
1
|
+
import{j as r,aC as J}from"./index-BZc5zH7u.js";import{r as a}from"./vendor-react-BWrEVJVb.js";import"./vendor-i18n-y9V7Sfuu.js";const h="hermes-chat:",I="hermes-chat-epoch:",Y=500,u=10,L=10;function q(s,l){if(!l)return null;try{const t=localStorage.getItem(I+s),c=localStorage.getItem(h+s)!=null;(t!==null&&t!==l||t===null&&c)&&localStorage.removeItem(h+s),t!==l&&localStorage.setItem(I+s,l)}catch{}return l}function P(s,l){q(s,l);try{const t=localStorage.getItem(h+s);if(!t)return[];const c=JSON.parse(t);return Array.isArray(c)?c.filter(n=>n&&(n.role==="user"||n.role==="assistant"||n.role==="system")).map(n=>({role:n.role,content:String(n.content??""),error:!!n.error})):[]}catch{return[]}}function X({instanceId:s,instanceEpoch:l=null}){const[t,c]=a.useState(()=>P(s,l)),[n,m]=a.useState(()=>Math.min(u,t.length||u)),[v,S]=a.useState(""),[d,N]=a.useState(!1),[g,w]=a.useState(!1),x=a.useRef(null),M=a.useRef(t.length),f=a.useRef(null),F=t.slice(-n),j=n<t.length;a.useEffect(()=>{try{const e=t.filter(i=>!i.pending).slice(-Y);e.length===0?localStorage.removeItem(h+s):localStorage.setItem(h+s,JSON.stringify(e))}catch{}},[s,t]),a.useEffect(()=>{const e=P(s,l);c(e),m(Math.min(u,e.length||u))},[s,l]),a.useEffect(()=>{const e=x.current;if(e){if(f.current){const i=f.current.prevScrollHeight;e.scrollTop=e.scrollHeight-i,f.current=null;return}t.length>=M.current&&(e.scrollTop=e.scrollHeight),M.current=t.length}},[t,n]);const C=()=>{if(!j||g)return;w(!0);const e=x.current;e&&(f.current={prevScrollHeight:e.scrollHeight}),m(i=>Math.min(i+L,t.length)),requestAnimationFrame(()=>w(!1))},T=()=>{const e=x.current;!e||!j||g||e.scrollTop<40&&C()},E=async()=>{var H,R,k,A;const e=v.trim();if(!e||d)return;S(""),N(!0);const i={role:"user",content:e},K={role:"assistant",content:"",pending:!0},_=[...t,i,K];c(_);const $=_.slice(0,-1).slice(-20).map(o=>({role:o.role,content:o.content}));try{const o=await J(s,{model:"hermes-agent",messages:$,max_tokens:512}),p=((k=(R=(H=o==null?void 0:o.choices)==null?void 0:H[0])==null?void 0:R.message)==null?void 0:k.content)??((A=o==null?void 0:o.error)==null?void 0:A.message)??"(empty response)";c(b=>b.map((y,B)=>B===b.length-1?{role:"assistant",content:String(p)}:y))}catch(o){c(p=>p.map((b,y)=>y===p.length-1?{role:"assistant",content:(o==null?void 0:o.message)||"(request failed)",error:!0}:b))}finally{N(!1)}},O=e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),E())};return r.jsxs("div",{className:"overflow-hidden rounded-[22px] border border-[var(--border)] bg-[var(--card)] shadow-[0_18px_48px_rgba(15,23,42,0.06)] flex flex-col",style:{height:"calc(100vh - 160px)",minHeight:"500px"},children:[r.jsxs("div",{className:"px-5 py-3 border-b border-[var(--border)] flex items-center justify-between",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"inline-block w-2 h-2 rounded-full bg-emerald-500 shadow-[0_0_6px_rgba(16,185,129,0.7)]"}),r.jsx("span",{className:"text-sm font-medium text-foreground",children:"Chat"}),r.jsx("span",{className:"text-[10px] text-muted font-mono",children:"inline → /v1/chat/completions"})]}),t.length>0&&r.jsx("button",{onClick:()=>{c([]),m(u)},className:"text-xs text-muted hover:text-foreground transition-colors",disabled:d,children:"清空对话"})]}),r.jsxs("div",{ref:x,onScroll:T,className:"flex-1 overflow-y-auto p-5 space-y-3",children:[j&&r.jsx("div",{className:"flex justify-center py-1",children:r.jsx("button",{onClick:C,disabled:g,className:"text-xs text-muted hover:text-foreground transition-colors",children:g?"加载中...":`向上滚动或点击加载更早的 ${Math.min(L,t.length-n)} 条 (共 ${t.length} 条)`})}),t.length===0?r.jsxs("div",{className:"h-full flex flex-col items-center justify-center text-center",children:[r.jsx("div",{className:"text-4xl mb-3 opacity-40",children:"⚕"}),r.jsx("div",{className:"text-sm text-foreground/70 font-medium mb-1",children:"和 Hermes agent 开始对话"}),r.jsx("div",{className:"text-xs text-muted max-w-md",children:"消息会走完整的 agent loop(skills + tools + memory), 经 JishuShell LLM 代理转发到上游模型。首次请求因冷启动约 20-30 秒。"})]}):F.map((e,i)=>r.jsx("div",{className:`flex ${e.role==="user"?"justify-end":"justify-start"}`,children:r.jsx("div",{className:`max-w-[80%] rounded-2xl px-4 py-2.5 text-sm whitespace-pre-wrap break-words ${e.role==="user"?"bg-[#0066FF] text-white":e.error?"bg-red-500/10 border border-red-500/20 text-red-400":"bg-[var(--input-bg)] border border-[var(--border)] text-foreground"}`,children:e.pending?r.jsxs("span",{className:"inline-flex items-center gap-2 text-muted",children:[r.jsx("span",{className:"w-3 h-3 border-2 border-[#0066FF]/30 border-t-[#0066FF] rounded-full animate-spin"}),"agent 正在思考..."]}):e.content})},t.length-F.length+i))]}),r.jsx("div",{className:"p-4 border-t border-[var(--border)]",children:r.jsxs("div",{className:"flex gap-2",children:[r.jsx("textarea",{value:v,onChange:e=>S(e.target.value),onKeyDown:O,placeholder:"输入消息 (Enter 发送,Shift+Enter 换行)",rows:2,disabled:d,className:"flex-1 bg-[var(--input-bg)] border border-[var(--border)] rounded-lg px-3 py-2 text-sm text-foreground placeholder-[var(--muted)] focus:outline-none focus:ring-1 focus:ring-[#0066FF]/60 focus:border-[#0066FF]/60 resize-none"}),r.jsx("button",{onClick:E,disabled:!v.trim()||d,className:"self-end px-4 py-2 bg-[#0066FF] text-white rounded-lg text-sm font-medium hover:bg-[#0066FF]/90 disabled:opacity-40 transition-all duration-200",children:d?r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{className:"w-3 h-3 border-2 border-white/30 border-t-white rounded-full animate-spin"}),"发送中"]}):"发送"})]})})]})}export{X as HermesChatPanel};
|