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
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Post-publish smoke test: install the published jishushell package from
|
|
4
|
+
* the npm registry into an isolated prefix, then verify it boots.
|
|
5
|
+
*
|
|
6
|
+
* Steps:
|
|
7
|
+
* 1. npm install -g jishushell@{version} --prefix <tempdir> --registry <url>
|
|
8
|
+
* 2. Verify `jishushell version` output matches the expected version
|
|
9
|
+
* 3. Spawn `jishushell serve --port 0 --host 127.0.0.1`
|
|
10
|
+
* 4. Poll /api/auth/status until HTTP 200
|
|
11
|
+
* 5. Clean up temp dirs and kill the server
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node scripts/smoke-post-publish.mjs --version 0.4.30 [--registry http://...]
|
|
15
|
+
*
|
|
16
|
+
* Exit codes:
|
|
17
|
+
* 0 — smoke test passed
|
|
18
|
+
* 1 — smoke test failed
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { execFileSync, spawn } from "child_process";
|
|
22
|
+
import { mkdirSync, mkdtempSync, rmSync } from "fs";
|
|
23
|
+
import { tmpdir } from "os";
|
|
24
|
+
import { join } from "path";
|
|
25
|
+
import { setTimeout as delay } from "timers/promises";
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Constants
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
const DEFAULT_REGISTRY = "http://10.188.0.22:4873/";
|
|
32
|
+
const INSTALL_RETRY_ATTEMPTS = 3;
|
|
33
|
+
const INSTALL_RETRY_DELAY_MS = 2_000;
|
|
34
|
+
const STARTUP_TIMEOUT_MS = 20_000;
|
|
35
|
+
const HEALTH_POLL_INTERVAL_MS = 300;
|
|
36
|
+
const HEALTH_POLL_ATTEMPTS = 30;
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Argument parsing
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
function parseArgs() {
|
|
43
|
+
const args = process.argv.slice(2);
|
|
44
|
+
let version = "";
|
|
45
|
+
let registry = DEFAULT_REGISTRY;
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < args.length; i++) {
|
|
48
|
+
if (args[i] === "--version" && args[i + 1]) {
|
|
49
|
+
version = args[++i];
|
|
50
|
+
} else if (args[i] === "--registry" && args[i + 1]) {
|
|
51
|
+
registry = args[++i];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!version) {
|
|
56
|
+
console.error("[post-publish] ERROR: --version is required");
|
|
57
|
+
console.error("Usage: node scripts/smoke-post-publish.mjs --version 0.4.30 [--registry URL]");
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { version, registry };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Version normalization
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/** Strip leading 'v' for consistent comparison. */
|
|
69
|
+
function normalizeVersion(v) {
|
|
70
|
+
return v.trim().replace(/^v/, "");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Temp directory management
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
function createTempDirs() {
|
|
78
|
+
const base = mkdtempSync(join(tmpdir(), "jishushell-postpub-"));
|
|
79
|
+
const prefixDir = join(base, "npm-prefix");
|
|
80
|
+
const homeDir = join(base, "jishushell-home");
|
|
81
|
+
const cacheDir = join(base, "npm-cache");
|
|
82
|
+
const fakeHome = join(base, "fake-home");
|
|
83
|
+
|
|
84
|
+
for (const dir of [prefixDir, homeDir, cacheDir, fakeHome]) {
|
|
85
|
+
mkdirSync(dir, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { base, prefixDir, homeDir, cacheDir, fakeHome };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// npm install with retry
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
async function npmInstallGlobal({ version, registry, prefixDir, cacheDir, fakeHome }) {
|
|
96
|
+
const pkg = `jishushell@${version}`;
|
|
97
|
+
const npmArgs = [
|
|
98
|
+
"install", "--global",
|
|
99
|
+
"--prefix", prefixDir,
|
|
100
|
+
"--registry", registry,
|
|
101
|
+
"--cache", cacheDir,
|
|
102
|
+
"--no-fund", "--no-audit",
|
|
103
|
+
pkg,
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const env = {
|
|
107
|
+
...process.env,
|
|
108
|
+
HOME: fakeHome,
|
|
109
|
+
CI: "true",
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
for (let attempt = 1; attempt <= INSTALL_RETRY_ATTEMPTS; attempt++) {
|
|
113
|
+
try {
|
|
114
|
+
console.log(`[post-publish] npm install (attempt ${attempt}/${INSTALL_RETRY_ATTEMPTS}): ${pkg}`);
|
|
115
|
+
execFileSync("npm", npmArgs, {
|
|
116
|
+
encoding: "utf-8",
|
|
117
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
118
|
+
timeout: 120_000,
|
|
119
|
+
env,
|
|
120
|
+
});
|
|
121
|
+
console.log(`[post-publish] Install succeeded`);
|
|
122
|
+
return;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const stderr = err.stderr?.toString() || err.message;
|
|
125
|
+
console.error(`[post-publish] Install attempt ${attempt} failed: ${stderr.slice(0, 500)}`);
|
|
126
|
+
if (attempt < INSTALL_RETRY_ATTEMPTS) {
|
|
127
|
+
await delay(INSTALL_RETRY_DELAY_MS);
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error(`npm install failed after ${INSTALL_RETRY_ATTEMPTS} attempts`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Version verification
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
function verifyVersion({ binPath, expectedVersion, fakeHome }) {
|
|
140
|
+
console.log(`[post-publish] Verifying version: ${binPath} version`);
|
|
141
|
+
|
|
142
|
+
const output = execFileSync("node", [binPath, "version"], {
|
|
143
|
+
encoding: "utf-8",
|
|
144
|
+
timeout: 10_000,
|
|
145
|
+
env: {
|
|
146
|
+
...process.env,
|
|
147
|
+
HOME: fakeHome,
|
|
148
|
+
NODE_ENV: "test",
|
|
149
|
+
npm_package_version: "",
|
|
150
|
+
},
|
|
151
|
+
}).trim();
|
|
152
|
+
|
|
153
|
+
const actual = normalizeVersion(output.split("\n").filter(Boolean).pop() || "");
|
|
154
|
+
const expected = normalizeVersion(expectedVersion);
|
|
155
|
+
|
|
156
|
+
if (actual !== expected) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`Version mismatch: expected '${expected}', got '${actual}' (raw output: '${output}')`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(`[post-publish] Version OK: ${output}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Server boot + health check
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
|
|
169
|
+
async function verifyServerBoots({ binPath, homeDir, fakeHome }) {
|
|
170
|
+
console.log(`[post-publish] Starting server: ${binPath} serve --port 0 --host 127.0.0.1`);
|
|
171
|
+
|
|
172
|
+
let serverProcess;
|
|
173
|
+
try {
|
|
174
|
+
serverProcess = spawn("node", [binPath, "serve", "--port", "0", "--host", "127.0.0.1"], {
|
|
175
|
+
env: {
|
|
176
|
+
...process.env,
|
|
177
|
+
HOME: fakeHome,
|
|
178
|
+
JISHUSHELL_HOME: homeDir,
|
|
179
|
+
JISHUSHELL_JWT_SECRET: "ci-smoke-test-jwt-secret-that-is-at-least-32-chars",
|
|
180
|
+
NODE_ENV: "test",
|
|
181
|
+
npm_package_version: "",
|
|
182
|
+
},
|
|
183
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
184
|
+
});
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error(`[post-publish] Failed to spawn server process: ${err.message}`);
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
serverProcessRef = serverProcess;
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
// Discover the assigned port from stdout/stderr
|
|
194
|
+
const port = await new Promise((resolve, reject) => {
|
|
195
|
+
const timer = setTimeout(
|
|
196
|
+
() => reject(new Error("Server did not start within timeout")),
|
|
197
|
+
STARTUP_TIMEOUT_MS,
|
|
198
|
+
);
|
|
199
|
+
let output = "";
|
|
200
|
+
|
|
201
|
+
const onData = (chunk) => {
|
|
202
|
+
output += chunk.toString();
|
|
203
|
+
const match = output.match(/listening at http:\/\/127\.0\.0\.1:(\d+)/);
|
|
204
|
+
if (match) {
|
|
205
|
+
clearTimeout(timer);
|
|
206
|
+
resolve(parseInt(match[1], 10));
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
serverProcess.stdout.on("data", onData);
|
|
211
|
+
serverProcess.stderr.on("data", onData);
|
|
212
|
+
serverProcess.on("exit", (code) => {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
reject(
|
|
215
|
+
new Error(
|
|
216
|
+
`Server exited with code ${code} before becoming ready.\nOutput:\n${output}`,
|
|
217
|
+
),
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
console.log(`[post-publish] Server listening on port ${port}`);
|
|
223
|
+
|
|
224
|
+
// Poll /api/auth/status
|
|
225
|
+
let lastStatus = 0;
|
|
226
|
+
for (let i = 0; i < HEALTH_POLL_ATTEMPTS; i++) {
|
|
227
|
+
try {
|
|
228
|
+
const resp = await fetch(`http://127.0.0.1:${port}/api/auth/status`, {
|
|
229
|
+
signal: AbortSignal.timeout(2000),
|
|
230
|
+
});
|
|
231
|
+
lastStatus = resp.status;
|
|
232
|
+
if (resp.ok) {
|
|
233
|
+
console.log(`[post-publish] PASSED: /api/auth/status returned ${resp.status}`);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
// Server may not be fully ready yet
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (serverProcess.exitCode !== null) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
`Server exited unexpectedly with code ${serverProcess.exitCode}`,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await delay(HEALTH_POLL_INTERVAL_MS);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
throw new Error(
|
|
250
|
+
`/api/auth/status returned ${lastStatus} after ${HEALTH_POLL_ATTEMPTS} attempts`,
|
|
251
|
+
);
|
|
252
|
+
} finally {
|
|
253
|
+
// Always kill the server process
|
|
254
|
+
if (!serverProcess.killed && serverProcess.exitCode === null) {
|
|
255
|
+
serverProcess.kill("SIGTERM");
|
|
256
|
+
await delay(500);
|
|
257
|
+
if (serverProcess.exitCode === null) {
|
|
258
|
+
try {
|
|
259
|
+
serverProcess.kill("SIGKILL");
|
|
260
|
+
} catch {
|
|
261
|
+
/* already dead */
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Process-level cleanup (CI cancel / timeout sends SIGTERM)
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
let serverProcessRef = null;
|
|
273
|
+
let tempBaseDir = null;
|
|
274
|
+
|
|
275
|
+
function emergencyCleanup(exitCode) {
|
|
276
|
+
if (serverProcessRef && !serverProcessRef.killed) {
|
|
277
|
+
try { serverProcessRef.kill("SIGKILL"); } catch { /* already dead */ }
|
|
278
|
+
}
|
|
279
|
+
if (tempBaseDir) {
|
|
280
|
+
try { rmSync(tempBaseDir, { recursive: true, force: true }); } catch { /* noop */ }
|
|
281
|
+
}
|
|
282
|
+
process.exit(exitCode);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
process.on("SIGINT", () => emergencyCleanup(1));
|
|
286
|
+
process.on("SIGTERM", () => emergencyCleanup(1));
|
|
287
|
+
process.on("unhandledRejection", (err) => {
|
|
288
|
+
console.error("[post-publish] unhandled rejection:", err);
|
|
289
|
+
emergencyCleanup(1);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ---------------------------------------------------------------------------
|
|
293
|
+
// Main
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
|
|
296
|
+
async function main() {
|
|
297
|
+
const { version, registry } = parseArgs();
|
|
298
|
+
const dirs = createTempDirs();
|
|
299
|
+
tempBaseDir = dirs.base;
|
|
300
|
+
|
|
301
|
+
const binPath = join(dirs.prefixDir, "bin", "jishushell");
|
|
302
|
+
|
|
303
|
+
console.log(`[post-publish] ─────────────────────────────────────────`);
|
|
304
|
+
console.log(`[post-publish] Version: ${version}`);
|
|
305
|
+
console.log(`[post-publish] Registry: ${registry}`);
|
|
306
|
+
console.log(`[post-publish] Prefix: ${dirs.prefixDir}`);
|
|
307
|
+
console.log(`[post-publish] Home: ${dirs.homeDir}`);
|
|
308
|
+
console.log(`[post-publish] ─────────────────────────────────────────`);
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
await npmInstallGlobal({
|
|
312
|
+
version,
|
|
313
|
+
registry,
|
|
314
|
+
prefixDir: dirs.prefixDir,
|
|
315
|
+
cacheDir: dirs.cacheDir,
|
|
316
|
+
fakeHome: dirs.fakeHome,
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
verifyVersion({
|
|
320
|
+
binPath,
|
|
321
|
+
expectedVersion: version,
|
|
322
|
+
fakeHome: dirs.fakeHome,
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
await verifyServerBoots({
|
|
326
|
+
binPath,
|
|
327
|
+
homeDir: dirs.homeDir,
|
|
328
|
+
fakeHome: dirs.fakeHome,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
console.log(`[post-publish] ✅ Post-publish smoke test PASSED`);
|
|
332
|
+
} finally {
|
|
333
|
+
// Clean up all temp directories
|
|
334
|
+
try {
|
|
335
|
+
rmSync(dirs.base, { recursive: true, force: true });
|
|
336
|
+
console.log(`[post-publish] Cleaned up temp dirs`);
|
|
337
|
+
} catch {
|
|
338
|
+
console.warn(`[post-publish] Warning: failed to clean up ${dirs.base}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
main().catch((err) => {
|
|
344
|
+
console.error(`[post-publish] ❌ FAILED: ${err.message}`);
|
|
345
|
+
process.exit(1);
|
|
346
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{k as B,j as e,L as E,l as k,m as M,n as R,o as K,q as L,t as A,v as I,w as T,x as W}from"./index-DQsM6Joa.js";import{r as m,u as D}from"./vendor-react-Bk1hRGiY.js";import{u as P}from"./usePolling-Do5Erqm_.js";import{u as C}from"./vendor-i18n-ucpM0OR0.js";function q(t){if(!t)return"-";const l=Math.floor(t/86400),d=Math.floor(t%86400/3600),r=Math.floor(t%3600/60);return l>0?`${l}d ${d}h`:d>0?`${d}h ${r}m`:`${r}m`}function G({status:t}){const{t:l}=C(),r={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 ${r.cls}`,children:l(r.labelKey)})}function z(){const{t}=C(["dashboard","common"]),[l,d]=m.useState([]),[r,$]=m.useState(null),[h,v]=m.useState(""),[y,j]=m.useState(""),[p,N]=m.useState(!1),g=D(),{showToast:c}=B(),u=()=>{K().then(s=>{d(s),j("")}).catch(s=>j(s.message||t("common:error.loadFailed"))),L().then($).catch(()=>{})};P(u,1e4);const _=async()=>{if(window.confirm(t("engine.restartConfirm"))){N(!0);try{await A(),c(t("engine.restarted"),"success"),setTimeout(u,2e3)}catch(s){c(s.message||t("engine.restartFailed"),"error")}finally{N(!1)}}},f=async(s,a,i)=>{s.stopPropagation(),v(`${i}-${a}`);try{let n=null;a==="start"&&(n=await I(i)),a==="stop"&&(n=await T(i)),a==="restart"&&(n=await W(i)),c(t(`common:action.${a}Done`),"success");const o=n==null?void 0:n.port_allocation;o&&typeof o.from=="number"&&typeof o.to=="number"&&o.from!==o.to&&c(t("common:toast.portReallocated",{defaultValue:"端口 {{from}} 被占用,已自动切换到 {{to}}",from:o.from,to:o.to}),"info"),setTimeout(u,1e3)}catch(n){c(n.message||t("common:error.operationFailed"),"error")}finally{v("")}},F=l.filter(s=>{var a;return((a=s.service)==null?void 0:a.status)==="running"}).length,b=!!r&&r.disk.percent>90,S=r?[{label:t("stats.runningInstances"),value:`${F} / ${l.length}`,sub:r.nomad_running?t("stats.engineRunning"):t("stats.engineStopped"),subColor:r.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:`${r.cpu_percent}%`,sub:r.temperature?`${r.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:r.cpu_percent>90},{label:t("stats.memory"),value:`${r.memory.percent}%`,sub:`${r.memory.used_mb}MB / ${r.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:`${r.disk.percent}%`,sub:`${r.disk.used_gb}GB / ${r.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:b?"text-red-400":"text-[#0066FF]",glowColor:b?"rgba(239,68,68,0.12)":"rgba(0,102,255,0.12)",accent:b?"border-l-2 border-l-red-400":"border-l-2 border-l-[#0066FF]",warn:b}]:[];return e.jsxs("div",{className:"p-4 max-w-5xl 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(E,{})]}),r&&e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-3 mb-4",children:S.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:()=>g("/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:()=>g("/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:_,disabled:p,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(k,{className:`w-3 h-3 ${p?"animate-spin":""}`}),t(p?"instances.restarting":"instances.restartEngine")]})]})]}),y?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:y})}),e.jsx("button",{onClick:u,className:"text-xs text-muted hover:text-foreground underline",children:t("common:action.retry")})]}):l.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-right font-medium px-4 py-2",children:t("table.actions")})]})}),e.jsx("tbody",{className:"divide-y divide-[var(--border)]",children:l.map(s=>{var n,o,w;const a=((n=s.service)==null?void 0:n.status)||"stopped",i=a==="running";return e.jsxs("tr",{className:"hover:bg-[var(--card-hover)] cursor-pointer transition-colors duration-150",onClick:()=>g(`/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(G,{status:a}),((o=s.auto_backup)==null?void 0:o.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:i?q(s.service.uptime):"-"}),e.jsx("td",{className:"px-4 py-2.5 text-muted hidden md:table-cell font-mono text-xs",children:(w=s.service)!=null&&w.memory_mb?`${s.service.memory_mb} MB`:"-"}),e.jsx("td",{className:"px-4 py-2.5 text-right",children:e.jsx("div",{className:"inline-flex items-center gap-1",children:i||a==="pending"?e.jsxs(e.Fragment,{children:[e.jsx("button",{title:t("common:action.restart"),onClick:x=>f(x,"restart",s.id),disabled:!!h,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(k,{className:"w-3.5 h-3.5"})}),e.jsx("button",{title:t("common:action.stop"),onClick:x=>f(x,"stop",s.id),disabled:!!h,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(M,{className:"w-3.5 h-3.5"})})]}):e.jsx("button",{title:t("common:action.start"),onClick:x=>f(x,"start",s.id),disabled:!!h,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(R,{className:"w-3.5 h-3.5"})})})})]},s.id)})})]})]})]})}export{z as default};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{ay as pe,j as s,p as ve,X as fe}from"./index-DQsM6Joa.js";import{r as u,L as Z}from"./vendor-react-Bk1hRGiY.js";import{g as ge}from"./input-paste-CrNVAyOy.js";import{P as S}from"./providers-V-vwrExZ.js";import{S as U,F as v,a as R,b as ee,I as K,c as ye,W as be}from"./WeixinLoginPanel-CnjR8xMu.js";import{u as je}from"./vendor-i18n-ucpM0OR0.js";const Ne=new Set(["feishu","weixin"]),F={telegram:{label:"Telegram",fields:[{key:"token",envKey:"TELEGRAM_BOT_TOKEN",label:"Bot Token",secret:!0,hint:"从 @BotFather 获取"},{key:"allowed",envKey:"TELEGRAM_ALLOWED_USERS",label:"Allowed Users",hint:"逗号分隔 user id,留空=所有人"}]},discord:{label:"Discord",fields:[{key:"token",envKey:"DISCORD_BOT_TOKEN",label:"Bot Token",secret:!0,hint:"从 Discord Developer Portal"}]},slack:{label:"Slack",fields:[{key:"bot",envKey:"SLACK_BOT_TOKEN",label:"Bot Token (xoxb-…)",secret:!0,placeholder:"xoxb-..."},{key:"app",envKey:"SLACK_APP_TOKEN",label:"App Token (xapp-…)",secret:!0,placeholder:"xapp-..."}]},whatsapp:{label:"WhatsApp",fields:[{key:"token",envKey:"WHATSAPP_TOKEN",label:"Access Token",secret:!0}]},signal:{label:"Signal",fields:[{key:"account",envKey:"SIGNAL_ACCOUNT",label:"Phone (E.164)",placeholder:"+8613800138000"}]},email:{label:"Email (SMTP)",fields:[{key:"host",envKey:"SMTP_HOST",label:"SMTP Host",placeholder:"smtp.gmail.com"},{key:"port",envKey:"SMTP_PORT",label:"SMTP Port",placeholder:"587"},{key:"user",envKey:"SMTP_USER",label:"SMTP User"},{key:"pass",envKey:"SMTP_PASSWORD",label:"SMTP Password",secret:!0}]}};function Ae(l){const m=new Map;for(const f of l.split(`
|
|
2
|
-
`)){const x=f.trim();if(!x||x.startsWith("#"))continue;const o=x.indexOf("=");if(o<0)continue;const c=x.slice(0,o).trim();let r=x.slice(o+1).trim();(r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'"))&&(r=r.slice(1,-1)),m.set(c,r)}return m}function se(l,m){const f=l.split(`
|
|
3
|
-
`),x=new Set,o=[];for(const c of f){const r=c.trim();if(!r||r.startsWith("#")){o.push(c);continue}const g=r.indexOf("=");if(g<0){o.push(c);continue}const N=r.slice(0,g).trim();if(N in m){x.add(N);const C=m[N];if(C==="")continue;o.push(`${N}=${C}`)}else o.push(c)}for(const[c,r]of Object.entries(m))!x.has(c)&&r!==""&&o.push(`${c}=${r}`);return o.join(`
|
|
4
|
-
`)}function Ce({config:l,onChange:m,instanceId:f,capabilities:x}){var X;const{t:o}=je(["instance","common"]),c=String((l==null?void 0:l.yaml)||""),r=String((l==null?void 0:l.env)||""),g=u.useMemo(()=>Ae(r),[r]),a=(((l==null?void 0:l["x-jishushell"])||{}).proxy||{}).upstream||{},h=a.providerId||"",k=S.find(e=>e.id===h),E=a.models||[],M=k?k.models.map(e=>({id:e.id,name:e.name,contextWindow:e.contextWindow})):E.map(e=>({id:e.id,name:e.name||e.id,contextWindow:e.contextWindow||0})),y=a.selectedModelId||((X=M[0])==null?void 0:X.id)||"",w=E.find(e=>e.id===y)||M.find(e=>e.id===y)||{id:"",name:"",contextWindow:0},[j,te]=u.useState(null),[T,oe]=u.useState(!1),[I,ne]=u.useState(!(a.hasApiKey&&h)),[H,D]=u.useState([]),[re,le]=u.useState([]),[O,V]=u.useState(!1);u.useEffect(()=>{pe().then(te).catch(()=>{})},[]);const P=e=>{var n;const t=JSON.parse(JSON.stringify(l));t["x-jishushell"]||(t["x-jishushell"]={}),(n=t["x-jishushell"]).proxy||(n.proxy={}),t["x-jishushell"].proxy.upstream={...t["x-jishushell"].proxy.upstream||{},...e},m(t)},W=(e,t)=>P({[e]:t}),ae=e=>{var d,i;const t=S.find(p=>p.id===e);if(!t){P({providerId:""});return}if(a.apiKey&&!window.confirm(o("configForm.switchProviderConfirm",{defaultValue:"切换 provider 会清空当前 API key,确定继续?"})))return;const n=JSON.parse(JSON.stringify(l));n["x-jishushell"]||(n["x-jishushell"]={}),(d=n["x-jishushell"]).proxy||(d.proxy={}),n["x-jishushell"].proxy.upstream={providerId:t.id,baseUrl:t.baseUrl,api:t.api,authHeader:t.authHeader===!0,headers:t.headers||{},models:t.models.map(p=>({id:p.id,name:p.name,contextWindow:p.contextWindow})),selectedModelId:((i=t.models[0])==null?void 0:i.id)||"",apiKey:"",hasApiKey:!1,clearApiKey:!1},m(n)},B=e=>W("selectedModelId",e),_=e=>{var p;const t=[...E],n=t.findIndex(b=>b.id===y),d={...w,...e};n>=0?t[n]=d:t.push(d);const i=JSON.parse(JSON.stringify(l));i["x-jishushell"]||(i["x-jishushell"]={}),(p=i["x-jishushell"]).proxy||(p.proxy={}),i["x-jishushell"].proxy.upstream={...i["x-jishushell"].proxy.upstream||{},models:t,selectedModelId:typeof e.id=="string"&&e.id?e.id:y},m(i)},$=async e=>{if(!h)return;const t=S.find(b=>b.id===h);if(!t)return;const d=["ollama","vllm","sglang"].includes(h)&&a.baseUrl?String(a.baseUrl):t.baseUrl,i=t.authHeader?"x-api-key":"Authorization",p=e??(a.apiKey||"");V(!0);try{const{models:b}=await ve(d,p,i);le(b),b.length&&!y&&B(b[0].id)}catch{}finally{V(!1)}},ie=e=>{if(!h||O)return;const t=ge(a.apiKey||"",e).trim();t&&$(t)},A=Array.isArray(x==null?void 0:x.messagingPlatforms)?x.messagingPlatforms:[],L=u.useMemo(()=>A.filter(e=>!Ne.has(e)),[A]),J=u.useMemo(()=>{const e=[];for(const t of L){const n=F[t];n&&n.fields.some(d=>(g.get(d.envKey)||"").trim()!=="")&&e.push(t)}return e},[L,g]),G=u.useMemo(()=>Array.from(new Set([...J,...H])),[J,H]),z=L.filter(e=>!G.includes(e)&&F[e]),Y=g.get("FEISHU_APP_ID")||"",de=u.useMemo(()=>{const e=c.match(/platforms:\s*[\s\S]*?feishu:\s*[\s\S]*?domain_name:\s*["']?(\w+)["']?/);return(e==null?void 0:e[1])==="lark"?"lark":"feishu"},[c]),q=()=>{f&&fe(f).then(e=>{e&&m(e)}).catch(()=>{})},Q=(e,t)=>{m({...l,format:"yaml+env",yaml:c,env:se(r,{[e]:t})})},ce=e=>{D(t=>t.includes(e)?t:[...t,e])},me=e=>{const t=F[e];if(!t)return;const n={};t.fields.forEach(d=>{n[d.envKey]=""}),m({...l,format:"yaml+env",yaml:c,env:se(r,n)}),D(d=>d.filter(i=>i!==e))},xe=e=>m({...l,format:"yaml+env",yaml:e,env:r}),he=e=>m({...l,format:"yaml+env",yaml:c,env:e}),ue=[...new Set(S.map(e=>e.group))];return s.jsxs("div",{className:"space-y-4",children:[s.jsxs(U,{title:o("configForm.modelConfig"),children:[s.jsxs("div",{className:"bg-[var(--card)] border border-[var(--border)] rounded-lg p-3 text-sm text-muted",children:[s.jsx("div",{className:"font-medium text-foreground mb-1",children:o("configForm.proxyChain")}),s.jsx("p",{children:o("configForm.proxyChainDesc")}),s.jsxs("div",{className:"mt-2 text-xs text-muted opacity-60 space-y-1",children:[s.jsxs("div",{children:["面板全局 provider:"," ",j!=null&&j.configured?s.jsxs("span",{className:"font-mono",children:[j.providerId,j.selectedModelId?` · ${j.selectedModelId}`:""]}):s.jsx(Z,{to:"/settings",className:"text-amber-400 underline hover:text-amber-300",children:"未配置"})," ",s.jsx(Z,{to:"/settings",className:"text-[#0066FF] hover:text-[#0066FF]/80",children:"(修改)"})]}),s.jsx("div",{className:"opacity-70",children:"本实例 API key 留空 → 自动回退全局 key (src/services/llm-proxy/index.ts:137)"})]})]}),!I&&s.jsx("button",{type:"button",onClick:()=>ne(!0),className:"text-xs text-[#0066FF] hover:text-[#0066FF]/80 transition-colors",children:o("configForm.editModelConfig")}),I&&s.jsx(v,{label:o("configForm.upstreamProvider"),hint:o("configForm.upstreamProviderHint"),children:s.jsxs(R,{value:h,onChange:ae,children:[s.jsx("option",{value:"",children:o("configForm.selectProvider")}),!k&&h&&s.jsxs("option",{value:h,children:[h," ",o("configForm.custom")]}),ue.map(e=>s.jsx("optgroup",{label:o(`configForm.providerGroup.${e}`,{defaultValue:e}),children:S.filter(t=>t.group===e).map(t=>s.jsx("option",{value:t.id,children:o(`configForm.providerLabel.${t.id}`,{defaultValue:t.label})},t.id))},e))]})}),I&&!["ollama","vllm","sglang"].includes(h)&&h&&s.jsxs(s.Fragment,{children:[s.jsxs(v,{label:o("configForm.upstreamApiKey"),hint:a.hasApiKey&&!a.clearApiKey?o("configForm.apiKeyHintSaved"):o("configForm.apiKeyHintNew"),children:[s.jsx(ee,{value:a.apiKey||"",saved:a.hasApiKey&&!a.clearApiKey,onChange:e=>P({apiKey:e,clearApiKey:!1}),onPaste:ie,placeholder:o("configForm.enterApiKey")}),a.hasApiKey&&s.jsx("button",{type:"button",onClick:()=>P({apiKey:"",clearApiKey:!a.clearApiKey}),className:"text-xs text-muted hover:text-foreground transition-colors mt-2",children:a.clearApiKey?o("configForm.restoreApiKey"):o("configForm.clearApiKey")})]}),s.jsx(v,{label:o("configForm.selectedModel"),children:s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("div",{className:"flex-1",children:s.jsxs(R,{value:y,onChange:B,children:[s.jsx("option",{value:"",children:o("configForm.selectModel")}),M.map(e=>s.jsxs("option",{value:e.id,children:[e.name||e.id,e.contextWindow?` (${Math.round(e.contextWindow/1e3)}K)`:""]},e.id)),re.filter(e=>!M.some(t=>t.id===e.id)).map(e=>s.jsx("option",{value:e.id,children:e.name||e.id},e.id))]})}),s.jsx("button",{type:"button",onClick:()=>{$()},disabled:O||!h,className:"px-3 py-2 border border-[var(--border)] text-muted rounded-md text-xs hover:bg-[var(--card-hover)] hover:text-foreground disabled:opacity-40 transition-colors",children:O?o("common:label.loading",{defaultValue:"加载中"}):o("configForm.fetchModels",{defaultValue:"拉取模型"})})]})}),s.jsx("button",{type:"button",onClick:()=>oe(!T),className:"text-xs text-muted hover:text-foreground transition-colors",children:o(T?"configForm.collapseAdvanced":"configForm.advancedOptions")}),T&&s.jsxs("div",{className:"space-y-4 border-t border-[var(--border)] pt-4",children:[s.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[s.jsx(v,{label:o("configForm.upstreamBaseUrl"),children:s.jsx(K,{value:a.baseUrl||"",onChange:e=>W("baseUrl",e),placeholder:o("configForm.baseUrlPlaceholder"),mono:!0})}),s.jsx(v,{label:o("configForm.upstreamApiProtocol"),children:s.jsxs(R,{value:a.api||"openai-completions",onChange:e=>W("api",e),children:[s.jsx("option",{value:"openai-completions",children:"OpenAI Compatible"}),s.jsx("option",{value:"openai-responses",children:"OpenAI Responses"}),s.jsx("option",{value:"anthropic-messages",children:"Anthropic Messages"}),s.jsx("option",{value:"google-generative-ai",children:"Google Generative AI"}),s.jsx("option",{value:"ollama",children:"Ollama"})]})})]}),y&&s.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-4",children:[s.jsx(v,{label:o("configForm.modelId"),children:s.jsx(K,{value:w.id||"",onChange:e=>_({id:e}),placeholder:"model-id",mono:!0})}),s.jsx(v,{label:o("configForm.modelName"),children:s.jsx(K,{value:w.name||"",onChange:e=>_({name:e}),placeholder:"Model Name"})}),s.jsx(v,{label:o("configForm.contextWindow"),children:s.jsx(K,{value:String(w.contextWindow||""),onChange:e=>_({contextWindow:parseInt(e)||0}),placeholder:"200000",mono:!0})})]}),s.jsx("div",{className:"text-xs text-muted bg-[var(--card)] border border-[var(--border)] rounded-md p-3",children:o("configForm.proxyNote")})]})]})]}),A.length>0&&s.jsxs(U,{title:o("configForm.imChannelConfig"),children:[s.jsxs("p",{className:"text-xs text-muted",children:["Hermes 通过 ",s.jsx("code",{className:"font-mono text-[11px]",children:".env"})," 环境变量读取消息平台凭证。 保存后重启实例生效。"]}),A.includes("feishu")&&s.jsxs("div",{className:"border border-[var(--border)] rounded-lg p-4 space-y-3 bg-[var(--card)]",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("span",{className:"text-sm font-medium text-foreground",children:o("configForm.channel.feishu",{defaultValue:"飞书 / Lark"})}),s.jsx("span",{className:"text-[11px] text-muted font-mono",children:"feishu"})]}),s.jsx(ye,{instanceId:f,channelKey:"feishu",existingAppId:Y||void 0,existingDomain:Y?de:void 0,onConfigured:q})]}),A.includes("weixin")&&s.jsxs("div",{className:"border border-[var(--border)] rounded-lg p-4 space-y-3 bg-[var(--card)]",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("span",{className:"text-sm font-medium text-foreground",children:o("configForm.channel.weixin",{defaultValue:"个人微信"})}),s.jsx("span",{className:"text-[11px] text-muted font-mono",children:"weixin"})]}),s.jsx(be,{instanceId:f,onConfigured:q})]}),s.jsx("div",{className:"space-y-3",children:G.map(e=>{const t=F[e];return t?s.jsxs("div",{className:"border border-[var(--border)] rounded-lg p-4 space-y-3 bg-[var(--card)]",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("span",{className:"text-sm font-medium text-foreground",children:t.label}),s.jsx("span",{className:"text-[11px] text-muted font-mono",children:e})]}),s.jsx("button",{onClick:()=>me(e),className:"text-xs text-red-400 hover:text-red-300 transition-colors",children:o("configForm.remove")})]}),s.jsx("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:t.fields.map(n=>{const d=g.get(n.envKey)||"";return s.jsx(v,{label:n.label,hint:n.hint||`.env: ${n.envKey}`,children:n.secret?s.jsx(ee,{value:d,saved:!!d,onChange:i=>Q(n.envKey,i),placeholder:n.placeholder}):s.jsx(K,{value:d,onChange:i=>Q(n.envKey,i),placeholder:n.placeholder,mono:!0})},n.key)})})]},e):null})}),z.length>0&&s.jsxs("div",{className:"pt-2",children:[s.jsx("p",{className:"text-xs text-muted mb-2",children:o("configForm.addImChannel")}),s.jsx("div",{className:"flex flex-wrap gap-2",children:z.map(e=>{var t;return s.jsxs("button",{onClick:()=>ce(e),className:"px-3 py-1.5 text-xs border border-dashed rounded-md transition-colors duration-150 border-[var(--border)] text-muted hover:border-[var(--border-hover)] hover:text-foreground",children:["+ ",((t=F[e])==null?void 0:t.label)||e]},e)})})]})]}),s.jsxs(U,{title:"高级 (原始 YAML + .env)",defaultOpen:!1,children:[s.jsx("p",{className:"text-xs text-muted",children:"直接编辑 YAML / .env。上方 Channels 字段与此处同步 — 任一侧修改都会反映到另一侧。"}),s.jsxs("div",{className:"bg-[var(--card)] border border-[var(--border)] rounded-xl overflow-hidden",children:[s.jsx("div",{className:"border-b border-[var(--border)] px-4 py-2",children:s.jsx("span",{className:"text-xs font-medium text-muted",children:"config.yaml"})}),s.jsx("textarea",{value:c,onChange:e=>xe(e.target.value),className:"w-full font-mono text-[13px] p-4 min-h-[240px] focus:outline-none resize-y text-foreground bg-transparent",spellCheck:!1})]}),s.jsxs("div",{className:"bg-[var(--card)] border border-[var(--border)] rounded-xl overflow-hidden",children:[s.jsx("div",{className:"border-b border-[var(--border)] px-4 py-2",children:s.jsx("span",{className:"text-xs font-medium text-muted",children:".env"})}),s.jsx("textarea",{value:r,onChange:e=>he(e.target.value),className:"w-full font-mono text-[13px] p-4 min-h-[220px] focus:outline-none resize-y text-foreground bg-transparent",spellCheck:!1})]})]})]})}export{Ce as HermesConfigForm};
|