jishushell 0.4.30 → 0.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/apps/anythingllm-container.yaml +287 -0
  2. package/apps/browserless-chromium-container.yaml +18 -6
  3. package/apps/filebrowser-container.yaml +163 -0
  4. package/apps/openclaw-binary.yaml +8 -0
  5. package/apps/openclaw-container.yaml +9 -1
  6. package/apps/openclaw-with-searxng-container.yaml +4 -0
  7. package/apps/searxng-container.yaml +5 -4
  8. package/apps/weknora-container.yaml +471 -0
  9. package/dist/cli/panel.js.map +1 -1
  10. package/dist/config.d.ts +19 -0
  11. package/dist/config.js +99 -1
  12. package/dist/config.js.map +1 -1
  13. package/dist/install.js +3 -3
  14. package/dist/install.js.map +1 -1
  15. package/dist/routes/auth.js +2 -2
  16. package/dist/routes/auth.js.map +1 -1
  17. package/dist/routes/backup.js +64 -11
  18. package/dist/routes/backup.js.map +1 -1
  19. package/dist/routes/external-mounts.d.ts +17 -0
  20. package/dist/routes/external-mounts.js +73 -0
  21. package/dist/routes/external-mounts.js.map +1 -0
  22. package/dist/routes/file-mounts.d.ts +13 -0
  23. package/dist/routes/file-mounts.js +90 -0
  24. package/dist/routes/file-mounts.js.map +1 -0
  25. package/dist/routes/files-organize.d.ts +28 -0
  26. package/dist/routes/files-organize.js +167 -0
  27. package/dist/routes/files-organize.js.map +1 -0
  28. package/dist/routes/files.d.ts +31 -0
  29. package/dist/routes/files.js +321 -0
  30. package/dist/routes/files.js.map +1 -0
  31. package/dist/routes/instances.js +45 -7
  32. package/dist/routes/instances.js.map +1 -1
  33. package/dist/routes/internal.d.ts +2 -0
  34. package/dist/routes/internal.js +59 -0
  35. package/dist/routes/internal.js.map +1 -0
  36. package/dist/routes/setup.js +9 -9
  37. package/dist/routes/setup.js.map +1 -1
  38. package/dist/routes/system.js +1 -1
  39. package/dist/routes/system.js.map +1 -1
  40. package/dist/routes/webdav.d.ts +17 -0
  41. package/dist/routes/webdav.js +114 -0
  42. package/dist/routes/webdav.js.map +1 -0
  43. package/dist/server.js +341 -3
  44. package/dist/server.js.map +1 -1
  45. package/dist/services/app/app-compiler.d.ts +1 -1
  46. package/dist/services/app/app-compiler.js +5 -5
  47. package/dist/services/app/app-compiler.js.map +1 -1
  48. package/dist/services/app/app-manager.d.ts +1 -0
  49. package/dist/services/app/app-manager.js +172 -41
  50. package/dist/services/app/app-manager.js.map +1 -1
  51. package/dist/services/app/custom-manager.js.map +1 -1
  52. package/dist/services/app/hermes-agent-manager.js +1 -0
  53. package/dist/services/app/hermes-agent-manager.js.map +1 -1
  54. package/dist/services/app/ollama-manager.js +1 -1
  55. package/dist/services/app/ollama-manager.js.map +1 -1
  56. package/dist/services/app/openclaw-manager.js +20 -3
  57. package/dist/services/app/openclaw-manager.js.map +1 -1
  58. package/dist/services/app/platform-transform.d.ts +32 -0
  59. package/dist/services/app/platform-transform.js +65 -0
  60. package/dist/services/app/platform-transform.js.map +1 -0
  61. package/dist/services/app-passwords.d.ts +61 -0
  62. package/dist/services/app-passwords.js +173 -0
  63. package/dist/services/app-passwords.js.map +1 -0
  64. package/dist/services/backup-manager.d.ts +11 -0
  65. package/dist/services/backup-manager.js +177 -4
  66. package/dist/services/backup-manager.js.map +1 -1
  67. package/dist/services/connection-apply.d.ts +2 -0
  68. package/dist/services/connection-apply.js +55 -1
  69. package/dist/services/connection-apply.js.map +1 -1
  70. package/dist/services/connection-resolver.js +1 -1
  71. package/dist/services/connection-resolver.js.map +1 -1
  72. package/dist/services/connection-transactor.d.ts +2 -0
  73. package/dist/services/connection-transactor.js +12 -2
  74. package/dist/services/connection-transactor.js.map +1 -1
  75. package/dist/services/external-mounts.d.ts +40 -0
  76. package/dist/services/external-mounts.js +187 -0
  77. package/dist/services/external-mounts.js.map +1 -0
  78. package/dist/services/files-manager.d.ts +252 -0
  79. package/dist/services/files-manager.js +1075 -0
  80. package/dist/services/files-manager.js.map +1 -0
  81. package/dist/services/files-mounts.d.ts +42 -0
  82. package/dist/services/files-mounts.js +207 -0
  83. package/dist/services/files-mounts.js.map +1 -0
  84. package/dist/services/instance-manager.js +1 -23
  85. package/dist/services/instance-manager.js.map +1 -1
  86. package/dist/services/llm-proxy/index.js.map +1 -1
  87. package/dist/services/llm-proxy/ssrf.js +6 -2
  88. package/dist/services/llm-proxy/ssrf.js.map +1 -1
  89. package/dist/services/nomad-manager.d.ts +4 -0
  90. package/dist/services/nomad-manager.js +53 -19
  91. package/dist/services/nomad-manager.js.map +1 -1
  92. package/dist/services/organize/applier.d.ts +46 -0
  93. package/dist/services/organize/applier.js +218 -0
  94. package/dist/services/organize/applier.js.map +1 -0
  95. package/dist/services/organize/rules.d.ts +57 -0
  96. package/dist/services/organize/rules.js +286 -0
  97. package/dist/services/organize/rules.js.map +1 -0
  98. package/dist/services/organize/scanner.d.ts +50 -0
  99. package/dist/services/organize/scanner.js +366 -0
  100. package/dist/services/organize/scanner.js.map +1 -0
  101. package/dist/services/organize/store.d.ts +14 -0
  102. package/dist/services/organize/store.js +82 -0
  103. package/dist/services/organize/store.js.map +1 -0
  104. package/dist/services/panel-manager.js +20 -1
  105. package/dist/services/panel-manager.js.map +1 -1
  106. package/dist/services/process-manager.js +3 -2
  107. package/dist/services/process-manager.js.map +1 -1
  108. package/dist/services/runtime/adapters/hermes.js +1 -1
  109. package/dist/services/runtime/adapters/hermes.js.map +1 -1
  110. package/dist/services/runtime/adapters/openclaw-routes.d.ts +8 -2
  111. package/dist/services/runtime/adapters/openclaw-routes.js +68 -0
  112. package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -1
  113. package/dist/services/runtime/adapters/openclaw.d.ts +90 -0
  114. package/dist/services/runtime/adapters/openclaw.js +957 -45
  115. package/dist/services/runtime/adapters/openclaw.js.map +1 -1
  116. package/dist/services/runtime/instance.d.ts +1 -1
  117. package/dist/services/runtime/instance.js +1 -1
  118. package/dist/services/runtime/instance.js.map +1 -1
  119. package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +46 -0
  120. package/dist/services/runtime/mcp-shims/anythingllm-shim.js +281 -0
  121. package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +1 -0
  122. package/dist/services/runtime/mcp-shims/drive-shim.d.ts +54 -0
  123. package/dist/services/runtime/mcp-shims/drive-shim.js +489 -0
  124. package/dist/services/runtime/mcp-shims/drive-shim.js.map +1 -0
  125. package/dist/services/runtime/types.d.ts +31 -0
  126. package/dist/services/setup-manager.js +93 -18
  127. package/dist/services/setup-manager.js.map +1 -1
  128. package/dist/services/suggestions.js.map +1 -1
  129. package/dist/services/webdav/server.d.ts +24 -0
  130. package/dist/services/webdav/server.js +420 -0
  131. package/dist/services/webdav/server.js.map +1 -0
  132. package/dist/services/webdav/xml-builder.d.ts +73 -0
  133. package/dist/services/webdav/xml-builder.js +156 -0
  134. package/dist/services/webdav/xml-builder.js.map +1 -0
  135. package/dist/services/workspace-builder.d.ts +29 -0
  136. package/dist/services/workspace-builder.js +188 -0
  137. package/dist/services/workspace-builder.js.map +1 -0
  138. package/dist/types.d.ts +60 -0
  139. package/dist/utils/path-locks.d.ts +30 -0
  140. package/dist/utils/path-locks.js +63 -0
  141. package/dist/utils/path-locks.js.map +1 -0
  142. package/dist/utils/path-safety.d.ts +41 -0
  143. package/dist/utils/path-safety.js +119 -0
  144. package/dist/utils/path-safety.js.map +1 -0
  145. package/dist/utils/safe-write.d.ts +24 -0
  146. package/dist/utils/safe-write.js +82 -0
  147. package/dist/utils/safe-write.js.map +1 -0
  148. package/package.json +16 -1
  149. package/public/assets/Dashboard-BdWPtroF.js +1 -0
  150. package/public/assets/{HermesChatPanel-_GHoklgo.js → HermesChatPanel-B_2HlVBQ.js} +1 -1
  151. package/public/assets/{HermesConfigForm-anDnwUp_.js → HermesConfigForm-DVlhg3WV.js} +2 -2
  152. package/public/assets/{InitPassword-ZU9_-hDr.js → InitPassword-D7glTExX.js} +1 -1
  153. package/public/assets/InstanceDetail-CxSy2cpe.js +92 -0
  154. package/public/assets/{Login-BItXqYAJ.js → Login-Cfr5c2sv.js} +1 -1
  155. package/public/assets/NewInstance-BIYDmJis.js +1 -0
  156. package/public/assets/{ProviderRecommendations-DFYj7Fb6.js → ProviderRecommendations-BuRnvRcI.js} +1 -1
  157. package/public/assets/{Settings-Bttc6QmM.js → Settings-Cc-tYBil.js} +1 -1
  158. package/public/assets/{Setup-Bsxx1zgj.js → Setup-lGZEk5jq.js} +1 -1
  159. package/public/assets/{WeixinLoginPanel-DPZpAKgO.js → WeixinLoginPanel-CoGqzxeV.js} +2 -2
  160. package/public/assets/index-87IJXG-w.css +1 -0
  161. package/public/assets/index-BZc5zH7u.js +19 -0
  162. package/public/assets/{registry-5s2UB6is.js → registry-BWnkJgZ1.js} +2 -2
  163. package/public/assets/{usePolling-Do5Erqm_.js → usePolling-CwwT9KrC.js} +1 -1
  164. package/public/assets/{vendor-i18n-ucpM0OR0.js → vendor-i18n-y9V7Sfuu.js} +1 -1
  165. package/public/assets/{vendor-react-Bk1hRGiY.js → vendor-react-BWrEVJVb.js} +6 -6
  166. package/public/index.html +4 -4
  167. package/scripts/check-app-spec.mjs +18 -4
  168. package/scripts/check-new-file-tests.mjs +230 -0
  169. package/scripts/check-quarantine-expiry.mjs +105 -0
  170. package/scripts/perf/README.md +49 -0
  171. package/scripts/perf/auth.js +99 -0
  172. package/scripts/perf/config.js +63 -0
  173. package/scripts/perf/instances.js +143 -0
  174. package/scripts/perf/proxy.js +96 -0
  175. package/scripts/smoke/files-w1.sh +142 -0
  176. package/scripts/smoke-backend.mjs +122 -0
  177. package/scripts/smoke-post-publish.mjs +346 -0
  178. package/public/assets/Dashboard-rkWp-CXd.js +0 -1
  179. package/public/assets/InstanceDetail-CN0FH1aw.js +0 -92
  180. package/public/assets/NewInstance-BousE6kY.js +0 -1
  181. package/public/assets/index-8xZy1z5k.css +0 -1
  182. package/public/assets/index-Dw3HhUYE.js +0 -19
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Atomic streaming writer (W1 PR-2).
3
+ *
4
+ * Main API is `atomicWriteStream` — pipes a Readable to a tmp file with
5
+ * optional streaming sha256, fdatasyncs, then renames to target. On any
6
+ * error the tmp is removed.
7
+ *
8
+ * `safeWriteBuffer` is a convenience wrapper for small Buffer payloads
9
+ * (e.g. .app-skills.json). It internally streams a single chunk.
10
+ *
11
+ * The caller is responsible for:
12
+ * - ensuring dirname(targetPath) exists (use mkdirSync recursive)
13
+ * - path validation (see path-safety.ts)
14
+ * - concurrent-write serialization on the same path (see path-locks.ts)
15
+ */
16
+ import { createWriteStream, openSync, fdatasyncSync, closeSync, renameSync, unlinkSync, existsSync, } from "node:fs";
17
+ import { pipeline } from "node:stream/promises";
18
+ import { Readable, Transform } from "node:stream";
19
+ import { createHash, randomBytes } from "node:crypto";
20
+ /**
21
+ * Stream `source` to `targetPath` atomically.
22
+ *
23
+ * Memory peak is the Node stream high-water-mark (~64KB), regardless of the
24
+ * total file size. Suitable for arbitrarily large files.
25
+ */
26
+ export async function atomicWriteStream(targetPath, source, opts = {}) {
27
+ const tmp = makeTmpName(targetPath);
28
+ let size = 0;
29
+ let hasher;
30
+ const writeStream = createWriteStream(tmp, { mode: opts.mode ?? 0o644 });
31
+ // We need a single Transform that both counts size and (optionally) hashes.
32
+ const counter = new Transform({
33
+ transform(chunk, _enc, cb) {
34
+ size += chunk.length;
35
+ hasher?.update(chunk);
36
+ cb(null, chunk);
37
+ },
38
+ });
39
+ if (opts.hash === "sha256") {
40
+ hasher = createHash("sha256");
41
+ }
42
+ try {
43
+ await pipeline(source, counter, writeStream);
44
+ if (opts.expectedSize !== undefined && size !== opts.expectedSize) {
45
+ throw new Error(`expected ${opts.expectedSize} bytes, got ${size}`);
46
+ }
47
+ // fdatasync tmp file before rename for crash safety
48
+ const fd = openSync(tmp, "r+");
49
+ try {
50
+ fdatasyncSync(fd);
51
+ }
52
+ finally {
53
+ closeSync(fd);
54
+ }
55
+ renameSync(tmp, targetPath);
56
+ return hasher
57
+ ? { size, hash: hasher.digest("hex") }
58
+ : { size };
59
+ }
60
+ catch (e) {
61
+ try {
62
+ if (existsSync(tmp))
63
+ unlinkSync(tmp);
64
+ }
65
+ catch {
66
+ // best-effort cleanup; surface the original error
67
+ }
68
+ throw e;
69
+ }
70
+ }
71
+ /**
72
+ * Convenience wrapper for small Buffer writes. Uses the same atomic pipeline.
73
+ */
74
+ export async function safeWriteBuffer(targetPath, buf, opts = {}) {
75
+ const source = Readable.from([buf]);
76
+ return atomicWriteStream(targetPath, source, opts);
77
+ }
78
+ function makeTmpName(target) {
79
+ const rand = randomBytes(8).toString("hex");
80
+ return `${target}.tmp.${process.pid}.${Date.now()}.${rand}`;
81
+ }
82
+ //# sourceMappingURL=safe-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-write.js","sourceRoot":"","sources":["../../src/utils/safe-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,iBAAiB,EACjB,QAAQ,EACR,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAgBtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAkB,EAClB,MAAgB,EAChB,OAA2B,EAAE;IAE7B,MAAM,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,IAAI,MAAiD,CAAC;IACtD,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IAEzE,4EAA4E;IAC5E,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC;QAC5B,SAAS,CAAC,KAAa,EAAE,IAAI,EAAE,EAAE;YAC/B,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACtB,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClB,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAE7C,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,YAAY,eAAe,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,oDAAoD;QACpD,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,aAAa,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;QAED,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAE5B,OAAO,MAAM;YACX,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YACtC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,GAAG,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,GAAW,EACX,OAA2B,EAAE;IAE7B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,OAAO,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,GAAG,MAAM,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC;AAC9D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jishushell",
3
- "version": "0.4.30",
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",
@@ -42,6 +51,7 @@
42
51
  "check:contracts": "node --experimental-strip-types scripts/check-adapter-isolation.ts",
43
52
  "check:i18n": "node scripts/check-i18n.mjs",
44
53
  "check:app-spec": "node scripts/check-app-spec.mjs",
54
+ "check:new-file-tests": "node scripts/check-new-file-tests.mjs",
45
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"
46
56
  },
47
57
  "engines": {
@@ -64,12 +74,17 @@
64
74
  "@fastify/static": "^8.1.0",
65
75
  "@noble/hashes": "^2.0.1",
66
76
  "bcryptjs": "^2.4.3",
77
+ "exifr": "^7.1.3",
67
78
  "fastify": "^5.2.0",
68
79
  "jsonwebtoken": "^9.0.2",
69
80
  "systeminformation": "^5.23.0",
70
81
  "yaml": "^2.8.3"
71
82
  },
72
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",
73
88
  "@types/bcryptjs": "^2.4.6",
74
89
  "@types/jsonwebtoken": "^9.0.7",
75
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,aC as J}from"./index-Dw3HhUYE.js";import{r as a}from"./vendor-react-Bk1hRGiY.js";import"./vendor-i18n-ucpM0OR0.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};
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};
@@ -1,4 +1,4 @@
1
- import{aD as pe,j as s,p as ve,$ as fe}from"./index-Dw3HhUYE.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-DtNXh9JD.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-DPZpAKgO.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(`
1
+ import{aD as pe,j as s,p as ve,$ as fe}from"./index-BZc5zH7u.js";import{r as u,L as Z}from"./vendor-react-BWrEVJVb.js";import{g as ge}from"./input-paste-CrNVAyOy.js";import{P as S}from"./providers-DtNXh9JD.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-CoGqzxeV.js";import{u as je}from"./vendor-i18n-y9V7Sfuu.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
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
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)),[D,H]=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)},$=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)},B=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,t.id,t.api);le(b),b.length&&!y&&$(b[0].id)}catch{}finally{V(!1)}},ie=e=>{if(!h||O)return;const t=ge(a.apiKey||"",e).trim();t&&B(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,...D])),[J,D]),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=>{H(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)}),H(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:$,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:()=>{B()},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};
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)),[D,H]=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)},$=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)},B=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,t.id,t.api);le(b),b.length&&!y&&$(b[0].id)}catch{}finally{V(!1)}},ie=e=>{if(!h||O)return;const t=ge(a.apiKey||"",e).trim();t&&B(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,...D])),[J,D]),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=>{H(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)}),H(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:$,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:()=>{B()},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,10)||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};
@@ -1 +1 @@
1
- import{j as e,L as j,T as v,I as w,a as N,c as y,s as F}from"./index-Dw3HhUYE.js";import{r}from"./vendor-react-Bk1hRGiY.js";import{u as S}from"./vendor-i18n-ucpM0OR0.js";const x="w-full bg-[var(--input-bg)] border border-[var(--border)] rounded-md px-3 py-2.5 text-sm text-foreground placeholder-[var(--muted)] focus:outline-none focus:ring-1 focus:ring-[#0066FF]/60 focus:border-[#0066FF]/60 transition-colors duration-200";function C({onDone:b}){const{t}=S("auth"),[s,p]=r.useState(""),[n,h]=r.useState(""),[o,f]=r.useState(!1),[l,d]=r.useState(""),[c,m]=r.useState(!1),u=s.length>=8&&s===n,g=async a=>{if(a.preventDefault(),!!u){d(""),m(!0);try{const i=await y(s);F(i.token),b()}catch(i){d(i.message||t("init.failed"))}finally{m(!1)}}};return e.jsxs("div",{className:"min-h-screen flex items-center justify-center p-4 bg-background relative overflow-hidden",children:[e.jsx("div",{className:"grid-bg absolute inset-0 pointer-events-none"}),e.jsx("div",{className:"absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] h-[300px] rounded-full bg-[#0066FF]/[0.07] blur-[90px] pointer-events-none"}),e.jsx("div",{className:"absolute left-4 bottom-4 z-20",children:e.jsx(j,{className:"bg-card/80 backdrop-blur-sm"})}),e.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx(v,{className:"w-40 h-40 mx-auto mb-4 object-contain"}),e.jsx("p",{className:"text-sm text-muted mt-1",children:t("init.title")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[l&&e.jsx("div",{className:"bg-red-500/10 border border-red-500/20 text-red-400 text-sm rounded-lg px-3 py-2.5",children:l}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-muted mb-1.5",children:t("init.password")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{type:o?"text":"password",value:s,onChange:a=>p(a.target.value),placeholder:t("init.passwordPlaceholder"),className:`${x} pr-10`,autoFocus:!0}),e.jsx("button",{type:"button",onClick:()=>f(!o),className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted hover:text-foreground transition-colors duration-200",children:o?e.jsx(w,{}):e.jsx(N,{})})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-muted mb-1.5",children:t("init.confirm")}),e.jsx("input",{type:o?"text":"password",value:n,onChange:a=>h(a.target.value),placeholder:t("init.confirmPlaceholder"),className:x}),s&&n&&s!==n&&e.jsx("p",{className:"text-red-400 text-xs mt-1.5",children:t("init.mismatch")})]}),e.jsx("button",{type:"submit",disabled:c||!u,className:"w-full bg-[#0066FF] text-white rounded-md py-2.5 text-sm font-medium hover:bg-[#0066FF]/90 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 shadow-[0_0_20px_rgba(0,102,255,0.3)] hover:shadow-[0_0_28px_rgba(0,102,255,0.45)]",children:c?e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx("span",{className:"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"}),t("init.loading")]}):t("init.submit")})]})]})]})}export{C as default};
1
+ import{j as e,L as j,T as v,I as w,a as N,c as y,s as F}from"./index-BZc5zH7u.js";import{r}from"./vendor-react-BWrEVJVb.js";import{u as S}from"./vendor-i18n-y9V7Sfuu.js";const x="w-full bg-[var(--input-bg)] border border-[var(--border)] rounded-md px-3 py-2.5 text-sm text-foreground placeholder-[var(--muted)] focus:outline-none focus:ring-1 focus:ring-[#0066FF]/60 focus:border-[#0066FF]/60 transition-colors duration-200";function C({onDone:b}){const{t}=S("auth"),[s,p]=r.useState(""),[o,h]=r.useState(""),[n,f]=r.useState(!1),[l,d]=r.useState(""),[c,m]=r.useState(!1),u=s.length>=8&&s===o,g=async a=>{if(a.preventDefault(),!!u){d(""),m(!0);try{const i=await y(s);F(i.token),b()}catch(i){d(i.message||t("init.failed"))}finally{m(!1)}}};return e.jsxs("div",{className:"min-h-screen flex items-center justify-center p-4 bg-background relative overflow-hidden",children:[e.jsx("div",{className:"grid-bg absolute inset-0 pointer-events-none"}),e.jsx("div",{className:"absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] h-[300px] rounded-full bg-[#0066FF]/[0.07] blur-[90px] pointer-events-none"}),e.jsx("div",{className:"absolute left-4 bottom-4 z-20",children:e.jsx(j,{className:"bg-card/80 backdrop-blur-sm"})}),e.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx(v,{className:"w-40 h-40 mx-auto mb-4 object-contain"}),e.jsx("p",{className:"text-sm text-muted mt-1",children:t("init.title")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[l&&e.jsx("div",{className:"bg-red-500/10 border border-red-500/20 text-red-400 text-sm rounded-lg px-3 py-2.5",children:l}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-muted mb-1.5",children:t("init.password")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{type:n?"text":"password",value:s,onChange:a=>p(a.target.value),placeholder:t("init.passwordPlaceholder"),className:`${x} pr-10`,autoFocus:!0}),e.jsx("button",{type:"button",onClick:()=>f(!n),"aria-label":t("common:action.togglePassword"),className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted hover:text-foreground transition-colors duration-200",children:n?e.jsx(w,{}):e.jsx(N,{})})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-muted mb-1.5",children:t("init.confirm")}),e.jsx("input",{type:n?"text":"password",value:o,onChange:a=>h(a.target.value),placeholder:t("init.confirmPlaceholder"),className:x}),s&&o&&s!==o&&e.jsx("p",{className:"text-red-400 text-xs mt-1.5",children:t("init.mismatch")})]}),e.jsx("button",{type:"submit",disabled:c||!u,className:"w-full bg-[#0066FF] text-white rounded-md py-2.5 text-sm font-medium hover:bg-[#0066FF]/90 disabled:opacity-40 disabled:cursor-not-allowed transition-all duration-200 shadow-[0_0_20px_rgba(0,102,255,0.3)] hover:shadow-[0_0_28px_rgba(0,102,255,0.45)]",children:c?e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx("span",{className:"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"}),t("init.loading")]}):t("init.submit")})]})]})]})}export{C as default};