jishushell 0.4.17 → 0.4.24

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 (241) hide show
  1. package/Dockerfile.hermes-slim +193 -0
  2. package/apps/hermes-container.yaml +35 -0
  3. package/apps/ollama-binary.yaml +200 -0
  4. package/apps/ollama-cpu-container.yaml +37 -0
  5. package/apps/ollama-with-hollama-binary.yaml +195 -0
  6. package/apps/openclaw-binary.yaml +69 -0
  7. package/apps/openclaw-container.yaml +37 -0
  8. package/apps/openclaw-with-ollama-container.yaml +42 -0
  9. package/apps/openclaw-with-searxng-container.yaml +136 -0
  10. package/apps/openwebui-container.yaml +53 -0
  11. package/apps/playwright-container.yaml +120 -0
  12. package/apps/searxng-container.yaml +115 -0
  13. package/dist/auth.d.ts +1 -0
  14. package/dist/auth.js +15 -14
  15. package/dist/auth.js.map +1 -1
  16. package/dist/cli/app.d.ts +1 -0
  17. package/dist/cli/app.js +710 -52
  18. package/dist/cli/app.js.map +1 -1
  19. package/dist/cli/backup.d.ts +3 -0
  20. package/dist/cli/backup.js +434 -0
  21. package/dist/cli/backup.js.map +1 -0
  22. package/dist/cli/doctor.d.ts +1 -0
  23. package/dist/cli/doctor.js +61 -35
  24. package/dist/cli/doctor.js.map +1 -1
  25. package/dist/cli/job.d.ts +1 -0
  26. package/dist/cli/job.js +37 -99
  27. package/dist/cli/job.js.map +1 -1
  28. package/dist/cli/llm.d.ts +1 -0
  29. package/dist/cli/llm.js +20 -14
  30. package/dist/cli/llm.js.map +1 -1
  31. package/dist/cli/managed-list.d.ts +30 -0
  32. package/dist/cli/managed-list.js +129 -0
  33. package/dist/cli/managed-list.js.map +1 -0
  34. package/dist/cli/panel.d.ts +4 -3
  35. package/dist/cli/panel.js +94 -24
  36. package/dist/cli/panel.js.map +1 -1
  37. package/dist/cli/version.d.ts +1 -0
  38. package/dist/cli/version.js +12 -0
  39. package/dist/cli/version.js.map +1 -0
  40. package/dist/cli.js +47 -516
  41. package/dist/cli.js.map +1 -1
  42. package/dist/config.d.ts +68 -0
  43. package/dist/config.js +266 -12
  44. package/dist/config.js.map +1 -1
  45. package/dist/control.d.ts +10 -6
  46. package/dist/control.js +87 -6
  47. package/dist/control.js.map +1 -1
  48. package/dist/install.d.ts +16 -0
  49. package/dist/install.js +75 -26
  50. package/dist/install.js.map +1 -1
  51. package/dist/routes/agent-apps.d.ts +15 -0
  52. package/dist/routes/agent-apps.js +78 -0
  53. package/dist/routes/agent-apps.js.map +1 -0
  54. package/dist/routes/apps.js +186 -7
  55. package/dist/routes/apps.js.map +1 -1
  56. package/dist/routes/backup.js +3 -3
  57. package/dist/routes/backup.js.map +1 -1
  58. package/dist/routes/instances.d.ts +6 -0
  59. package/dist/routes/instances.js +862 -879
  60. package/dist/routes/instances.js.map +1 -1
  61. package/dist/routes/llm.js +9 -8
  62. package/dist/routes/llm.js.map +1 -1
  63. package/dist/routes/runtime.d.ts +15 -0
  64. package/dist/routes/runtime.js +69 -0
  65. package/dist/routes/runtime.js.map +1 -0
  66. package/dist/routes/setup.js +103 -8
  67. package/dist/routes/setup.js.map +1 -1
  68. package/dist/routes/system.js +25 -3
  69. package/dist/routes/system.js.map +1 -1
  70. package/dist/server.js +71 -7
  71. package/dist/server.js.map +1 -1
  72. package/dist/services/agent-apps/catalog.d.ts +30 -0
  73. package/dist/services/agent-apps/catalog.js +60 -0
  74. package/dist/services/agent-apps/catalog.js.map +1 -0
  75. package/dist/services/agent-apps/index.d.ts +36 -0
  76. package/dist/services/agent-apps/index.js +171 -0
  77. package/dist/services/agent-apps/index.js.map +1 -0
  78. package/dist/services/agent-apps/installers/adapter-probes.d.ts +49 -0
  79. package/dist/services/agent-apps/installers/adapter-probes.js +223 -0
  80. package/dist/services/agent-apps/installers/adapter-probes.js.map +1 -0
  81. package/dist/services/agent-apps/installers/adapter.d.ts +30 -0
  82. package/dist/services/agent-apps/installers/adapter.js +171 -0
  83. package/dist/services/agent-apps/installers/adapter.js.map +1 -0
  84. package/dist/services/agent-apps/installers/registry-probe.d.ts +38 -0
  85. package/dist/services/agent-apps/installers/registry-probe.js +183 -0
  86. package/dist/services/agent-apps/installers/registry-probe.js.map +1 -0
  87. package/dist/services/agent-apps/installers/shell-script.d.ts +47 -0
  88. package/dist/services/agent-apps/installers/shell-script.js +471 -0
  89. package/dist/services/agent-apps/installers/shell-script.js.map +1 -0
  90. package/dist/services/agent-apps/types.d.ts +125 -0
  91. package/dist/services/agent-apps/types.js +17 -0
  92. package/dist/services/agent-apps/types.js.map +1 -0
  93. package/dist/services/{app-compiler.d.ts → app/app-compiler.d.ts} +3 -3
  94. package/dist/services/{app-compiler.js → app/app-compiler.js} +10 -7
  95. package/dist/services/app/app-compiler.js.map +1 -0
  96. package/dist/services/app/app-manager.d.ts +142 -0
  97. package/dist/services/app/app-manager.js +1988 -0
  98. package/dist/services/app/app-manager.js.map +1 -0
  99. package/dist/services/app/custom-manager.d.ts +27 -0
  100. package/dist/services/app/custom-manager.js +285 -0
  101. package/dist/services/app/custom-manager.js.map +1 -0
  102. package/dist/services/app/hermes-agent-manager.d.ts +20 -0
  103. package/dist/services/app/hermes-agent-manager.js +289 -0
  104. package/dist/services/app/hermes-agent-manager.js.map +1 -0
  105. package/dist/services/app/id-normalizer.d.ts +27 -0
  106. package/dist/services/app/id-normalizer.js +77 -0
  107. package/dist/services/app/id-normalizer.js.map +1 -0
  108. package/dist/services/app/ollama-manager.d.ts +18 -0
  109. package/dist/services/app/ollama-manager.js +207 -0
  110. package/dist/services/app/ollama-manager.js.map +1 -0
  111. package/dist/services/app/openclaw-manager.d.ts +63 -0
  112. package/dist/services/app/openclaw-manager.js +1178 -0
  113. package/dist/services/app/openclaw-manager.js.map +1 -0
  114. package/dist/services/app/paths.d.ts +47 -0
  115. package/dist/services/app/paths.js +68 -0
  116. package/dist/services/app/paths.js.map +1 -0
  117. package/dist/services/app/registry.d.ts +17 -0
  118. package/dist/services/app/registry.js +31 -0
  119. package/dist/services/app/registry.js.map +1 -0
  120. package/dist/services/app/remote-spec.d.ts +14 -0
  121. package/dist/services/app/remote-spec.js +58 -0
  122. package/dist/services/app/remote-spec.js.map +1 -0
  123. package/dist/services/app/terminal-session-manager.d.ts +27 -0
  124. package/dist/services/app/terminal-session-manager.js +157 -0
  125. package/dist/services/app/terminal-session-manager.js.map +1 -0
  126. package/dist/services/app/types.d.ts +72 -0
  127. package/dist/services/app/types.js +16 -0
  128. package/dist/services/app/types.js.map +1 -0
  129. package/dist/services/backup-manager.js +60 -22
  130. package/dist/services/backup-manager.js.map +1 -1
  131. package/dist/services/instance-manager.d.ts +82 -39
  132. package/dist/services/instance-manager.js +575 -1142
  133. package/dist/services/instance-manager.js.map +1 -1
  134. package/dist/services/llm-proxy/circuit-breaker.js +10 -2
  135. package/dist/services/llm-proxy/circuit-breaker.js.map +1 -1
  136. package/dist/services/llm-proxy/index.d.ts +14 -1
  137. package/dist/services/llm-proxy/index.js +51 -6
  138. package/dist/services/llm-proxy/index.js.map +1 -1
  139. package/dist/services/nomad-manager.d.ts +260 -3
  140. package/dist/services/nomad-manager.js +2866 -449
  141. package/dist/services/nomad-manager.js.map +1 -1
  142. package/dist/services/panel-manager.d.ts +10 -0
  143. package/dist/services/panel-manager.js +97 -0
  144. package/dist/services/panel-manager.js.map +1 -1
  145. package/dist/services/plugin-installer.js +28 -2
  146. package/dist/services/plugin-installer.js.map +1 -1
  147. package/dist/services/process-manager.js +22 -0
  148. package/dist/services/process-manager.js.map +1 -1
  149. package/dist/services/runtime/adapters/custom.d.ts +20 -0
  150. package/dist/services/runtime/adapters/custom.js +90 -0
  151. package/dist/services/runtime/adapters/custom.js.map +1 -0
  152. package/dist/services/runtime/adapters/hermes.d.ts +174 -0
  153. package/dist/services/runtime/adapters/hermes.js +1316 -0
  154. package/dist/services/runtime/adapters/hermes.js.map +1 -0
  155. package/dist/services/runtime/adapters/openclaw-routes.d.ts +17 -0
  156. package/dist/services/runtime/adapters/openclaw-routes.js +946 -0
  157. package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -0
  158. package/dist/services/runtime/adapters/openclaw.d.ts +188 -0
  159. package/dist/services/runtime/adapters/openclaw.js +2195 -0
  160. package/dist/services/runtime/adapters/openclaw.js.map +1 -0
  161. package/dist/services/runtime/errors.d.ts +28 -0
  162. package/dist/services/runtime/errors.js +31 -0
  163. package/dist/services/runtime/errors.js.map +1 -0
  164. package/dist/services/runtime/index.d.ts +34 -0
  165. package/dist/services/runtime/index.js +51 -0
  166. package/dist/services/runtime/index.js.map +1 -0
  167. package/dist/services/runtime/instance.d.ts +24 -0
  168. package/dist/services/runtime/instance.js +143 -0
  169. package/dist/services/runtime/instance.js.map +1 -0
  170. package/dist/services/runtime/migrations.d.ts +15 -0
  171. package/dist/services/runtime/migrations.js +25 -0
  172. package/dist/services/runtime/migrations.js.map +1 -0
  173. package/dist/services/runtime/registry.d.ts +13 -0
  174. package/dist/services/runtime/registry.js +32 -0
  175. package/dist/services/runtime/registry.js.map +1 -0
  176. package/dist/services/runtime/types.d.ts +545 -0
  177. package/dist/services/runtime/types.js +14 -0
  178. package/dist/services/runtime/types.js.map +1 -0
  179. package/dist/services/setup-manager.d.ts +70 -29
  180. package/dist/services/setup-manager.js +278 -597
  181. package/dist/services/setup-manager.js.map +1 -1
  182. package/dist/services/task-registry.d.ts +44 -0
  183. package/dist/services/task-registry.js +74 -0
  184. package/dist/services/task-registry.js.map +1 -0
  185. package/dist/services/telemetry/heartbeat.d.ts +6 -6
  186. package/dist/services/telemetry/heartbeat.js +29 -30
  187. package/dist/services/telemetry/heartbeat.js.map +1 -1
  188. package/dist/types.d.ts +162 -2
  189. package/dist/utils/docker-host.d.ts +15 -0
  190. package/dist/utils/docker-host.js +64 -0
  191. package/dist/utils/docker-host.js.map +1 -0
  192. package/install/jishu-install.sh +25 -1
  193. package/package.json +14 -4
  194. package/public/assets/Dashboard-B-JoOjBQ.js +1 -0
  195. package/public/assets/HermesChatPanel-mFSureyc.js +1 -0
  196. package/public/assets/HermesConfigForm-DvR05LK1.js +4 -0
  197. package/public/assets/InitPassword-CVA8wQA6.js +1 -0
  198. package/public/assets/InstanceDetail-DcZW2QGO.js +91 -0
  199. package/public/assets/{Login-D1Bt-Lyk.js → Login-BWsZH2mu.js} +1 -1
  200. package/public/assets/NewInstance-BCIrAd86.js +1 -0
  201. package/public/assets/Settings-xkDcduFz.js +1 -0
  202. package/public/assets/Setup-Cfuwj4gV.js +1 -0
  203. package/public/assets/WeixinLoginPanel-CnjR8xMu.js +9 -0
  204. package/public/assets/index-CPhVFEsx.css +1 -0
  205. package/public/assets/index-DQsM6Joa.js +19 -0
  206. package/public/assets/input-paste-CrNVAyOy.js +1 -0
  207. package/public/assets/registry-B4UFJdpA.js +2 -0
  208. package/public/assets/{usePolling-CK0DfI4h.js → usePolling-Do5Erqm_.js} +1 -1
  209. package/public/assets/vendor-i18n-ucpM0OR0.js +9 -0
  210. package/public/assets/{vendor-react-B1-3Yrt-.js → vendor-react-Bk1hRGiY.js} +1 -1
  211. package/public/favicon.png +0 -0
  212. package/public/index.html +9 -4
  213. package/public/logos/hermes.png +0 -0
  214. package/public/logos/ollama.png +0 -0
  215. package/public/logos/openclaw.svg +60 -0
  216. package/scripts/build-hermes-image.sh +21 -0
  217. package/scripts/build-local.sh +54 -0
  218. package/scripts/check-adapter-isolation.ts +293 -0
  219. package/scripts/fixtures/instances/hermes-sample/instance.json +37 -0
  220. package/scripts/fixtures/instances/legacy-openclaw-sample/instance.json +7 -0
  221. package/scripts/smoke/hermes-bootstrap.sh +195 -0
  222. package/templates/hermes-entrypoint.sh +154 -0
  223. package/dist/cli/openclaw.d.ts +0 -12
  224. package/dist/cli/openclaw.js +0 -156
  225. package/dist/cli/openclaw.js.map +0 -1
  226. package/dist/services/app-compiler.js.map +0 -1
  227. package/dist/services/app-manager.d.ts +0 -17
  228. package/dist/services/app-manager.js +0 -168
  229. package/dist/services/app-manager.js.map +0 -1
  230. package/dist/services/job-manager.d.ts +0 -22
  231. package/dist/services/job-manager.js +0 -102
  232. package/dist/services/job-manager.js.map +0 -1
  233. package/public/assets/Dashboard-CQsp1Mr9.js +0 -1
  234. package/public/assets/InitPassword-BEC8SE4A.js +0 -1
  235. package/public/assets/InstanceDetail-B5wTgNEg.js +0 -17
  236. package/public/assets/NewInstance-GQzm3K9D.js +0 -1
  237. package/public/assets/Settings-ByjGlqhP.js +0 -1
  238. package/public/assets/Setup-cMF21Y-8.js +0 -1
  239. package/public/assets/index-B6qQP4mH.css +0 -1
  240. package/public/assets/index-BuTQtuNy.js +0 -16
  241. package/public/assets/vendor-i18n-CfW0RvgE.js +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/services/telemetry/heartbeat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/services/telemetry/heartbeat.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -10,6 +10,22 @@ export interface ServiceResult {
10
10
  error?: string;
11
11
  warning?: string;
12
12
  pid?: number;
13
+ /**
14
+ * startInstance-only: tag identifying which phase of the start pipeline
15
+ * produced the error. Present on every error result returned by
16
+ * nomad-manager.startInstance so callers (routes, tests, logs) can
17
+ * distinguish where the failure happened.
18
+ */
19
+ phase?: "running_check" | "home_conflict" | "port_alloc" | "pre_start_hook" | "submit";
20
+ /** Adapter signaled an async background build; poll taskId for progress. */
21
+ building?: boolean;
22
+ taskId?: string;
23
+ /** Nomad alloc ID returned by waitForRunning / restartInstance. */
24
+ alloc_id?: string;
25
+ /** Nomad eval ID returned by submitJob. */
26
+ eval_id?: string;
27
+ /** Port allocation metadata from adapters (process-manager / nomad-manager). */
28
+ port_allocation?: unknown;
13
29
  }
14
30
  export interface ExecResult {
15
31
  stdout: string;
@@ -25,12 +41,54 @@ export interface ServiceManager {
25
41
  /** Run a command inside the running instance (docker exec or direct exec). */
26
42
  exec(id: string, command: string[], timeoutMs?: number): Promise<ExecResult>;
27
43
  }
44
+ /**
45
+ * Runtime catalog entry stored in panel.json.runtime_catalog.<agentType>.
46
+ * See docs/multi-agent-runtime-generalization-plan.md §32.1 (digest pin) and §32.3 (MVP shape).
47
+ * Fields are camelCase per §8 naming convention.
48
+ */
49
+ export interface RuntimeCatalogEntry {
50
+ defaultImage: string;
51
+ defaultImageDigest?: string;
52
+ shimPath?: string;
53
+ configFormat: "json" | "yaml+env" | "custom";
54
+ homeDirName: string;
55
+ resources: {
56
+ CPU: number;
57
+ MemoryMB: number;
58
+ MemoryMaxMB?: number;
59
+ };
60
+ allowDockerSock?: boolean;
61
+ }
62
+ export interface RuntimeCatalog {
63
+ openclaw?: RuntimeCatalogEntry;
64
+ hermes?: RuntimeCatalogEntry;
65
+ [agentType: string]: RuntimeCatalogEntry | undefined;
66
+ }
28
67
  export interface PanelConfig {
29
68
  service_manager?: "process" | "nomad";
30
69
  nomad_driver?: "docker";
70
+ /**
71
+ * Legacy openclaw image field. Still written by {@link setOpenclawDockerImage}
72
+ * for compatibility with older panel.json consumers; the authoritative value
73
+ * now lives in `runtime_catalog.openclaw.defaultImage`. Drop after one release
74
+ * cycle, together with the legacy read fallback in {@link getOpenclawDockerImage}.
75
+ */
31
76
  openclaw_image?: string;
32
77
  nomad_token?: string;
33
78
  allowed_origins?: string[];
79
+ /**
80
+ * Per-runtime catalog. Openclaw and Hermes both live here; `openclaw_image`
81
+ * is kept as a legacy mirror until the next major release.
82
+ */
83
+ runtime_catalog?: RuntimeCatalog;
84
+ /**
85
+ * Version of the `runtime_catalog` schema this panel.json was last written
86
+ * against. Panel code advertises the highest version it understands via
87
+ * `CURRENT_CATALOG_SCHEMA_VERSION`; a newer value here (written by a newer
88
+ * panel) triggers a startup warning and disables catalog mutations so a
89
+ * downgraded panel cannot silently corrupt structure it doesn't recognize.
90
+ */
91
+ runtime_catalog_schema_version?: number;
34
92
  default_provider?: {
35
93
  providerId?: string;
36
94
  baseUrl?: string;
@@ -51,6 +109,7 @@ export interface PanelConfig {
51
109
  }
52
110
  export type AppTaskRuntime = "container" | "process" | "vm";
53
111
  export type AppTaskRole = "service" | "init" | "sidecar" | "cleanup";
112
+ export type AppTaskPortVisibility = "external" | "internal" | "public";
54
113
  export interface AppTaskResources {
55
114
  cpu?: string;
56
115
  memory?: string;
@@ -58,7 +117,9 @@ export interface AppTaskResources {
58
117
  export interface AppTaskPort {
59
118
  name: string;
60
119
  port: number;
61
- visibility?: "public" | "internal";
120
+ host_port?: number;
121
+ container_port?: number;
122
+ visibility?: AppTaskPortVisibility;
62
123
  }
63
124
  export interface AppTaskHealth {
64
125
  http?: {
@@ -68,10 +129,23 @@ export interface AppTaskHealth {
68
129
  interval?: string;
69
130
  timeout?: string;
70
131
  retries?: number;
132
+ /** Grace period after start during which probe failures don't count. */
133
+ start_period?: string;
134
+ }
135
+ export interface AppDependsOnEntry {
136
+ /** Readiness condition: "started" | "completed" | "healthy" */
137
+ condition: "started" | "completed" | "healthy";
138
+ /** When true (default), dependency failure blocks this app. */
139
+ required?: boolean;
140
+ }
141
+ export interface AppTaskVolume {
142
+ source: string;
143
+ target: string;
144
+ readonly?: boolean;
71
145
  }
72
146
  export interface AppTask {
73
147
  name: string;
74
- role: AppTaskRole;
148
+ role?: AppTaskRole;
75
149
  runtime: AppTaskRuntime;
76
150
  image?: string;
77
151
  command?: string;
@@ -81,33 +155,119 @@ export interface AppTask {
81
155
  ports?: AppTaskPort[];
82
156
  health?: AppTaskHealth;
83
157
  after?: string[];
158
+ /** Volumes: string format "src:dest[:ro]" or object { source, target, readonly? } */
159
+ volumes?: Array<string | AppTaskVolume>;
160
+ }
161
+ export interface AppTerminalCommandPreset {
162
+ cmd: string;
163
+ label?: string;
164
+ description?: string;
165
+ }
166
+ export interface AppTerminalConfig {
167
+ /** Base argv prepended when the user enters only a sub-command. */
168
+ command: string[];
169
+ /** Optional task name for multi-task app specs; defaults to the first service task. */
170
+ task?: string;
171
+ prompt?: string;
172
+ welcome?: string;
173
+ timeout_ms?: number;
174
+ commands?: Record<string, Array<string | AppTerminalCommandPreset>>;
84
175
  }
85
176
  export interface AppProvide {
86
177
  capability: string;
87
178
  port?: number;
88
179
  path?: string;
180
+ url?: string;
181
+ protocol?: "http" | "https" | "tcp" | "udp" | (string & {});
89
182
  visibility?: string;
90
183
  description?: string;
184
+ terminal?: AppTerminalConfig;
91
185
  }
92
186
  export interface AppRequire {
93
187
  capability: string;
94
188
  inject_as: string;
95
189
  required?: boolean;
96
190
  }
191
+ export type AppLifecycleStep = {
192
+ run: string;
193
+ timeout_ms?: number;
194
+ successIfCommandExists?: string;
195
+ } | {
196
+ downloadImage: string;
197
+ timeout_ms?: number;
198
+ } | {
199
+ deleteImage: string;
200
+ } | {
201
+ downloadBinary: {
202
+ url: string;
203
+ dest: string;
204
+ chmod?: string;
205
+ };
206
+ } | {
207
+ deleteBinary: string;
208
+ } | {
209
+ mkdir: string;
210
+ } | {
211
+ deleteDir: string;
212
+ } | {
213
+ checkNotCommand: string;
214
+ message?: string;
215
+ };
216
+ export interface AppLifecycle {
217
+ pre_install?: AppLifecycleStep[];
218
+ /** Steps run during `app install`, before the job is created. */
219
+ install?: AppLifecycleStep[];
220
+ /** Steps run during `app uninstall`, before files are removed. */
221
+ uninstall?: AppLifecycleStep[];
222
+ /** Steps run after the Nomad job transitions to `running`. */
223
+ post_start?: AppLifecycleStep[];
224
+ }
97
225
  export interface AppSpec {
98
226
  id: string;
227
+ app_id?: string;
99
228
  name?: string;
100
229
  version?: string;
101
230
  description?: string;
231
+ /** Minimum JishuShell version required to install this app spec. */
232
+ jishushell?: {
233
+ min_version?: string;
234
+ };
235
+ /** When true (default), only one instance can be installed. When false, multiple instances get -1, -2 suffix. */
236
+ singleInstance?: boolean;
237
+ /** Custom prefix inserted before the numeric suffix for multi-instance naming. e.g. "inst" → ollama-inst1, ollama-inst2 */
238
+ instancePrefix?: string;
102
239
  tasks: AppTask[];
240
+ depends_on?: Record<string, AppDependsOnEntry>;
103
241
  provides?: AppProvide[];
104
242
  requires?: AppRequire[];
243
+ /**
244
+ * Target runtime for instances created from this spec. Drives the
245
+ * `adapter.createInstance()` dispatch in `routes/apps.ts`. When omitted,
246
+ * the app install flow defaults to `"openclaw"` for backward
247
+ * compatibility with specs authored before the multi-runtime contract
248
+ * (§32.2).
249
+ */
250
+ agentType?: string;
251
+ /**
252
+ * Runtime-scoped overlays the adapter applies during `createInstance()`.
253
+ * Plan §17 shape: `{ agentType?, defaults?, capabilities?, ... }`.
254
+ * Adapters are free to read extra keys (e.g. OpenClaw reads `skills` here).
255
+ */
256
+ runtime?: Record<string, any>;
257
+ lifecycle?: AppLifecycle;
258
+ /** @deprecated use `runtime` — kept as a legacy alias for pre-§17 specs. */
105
259
  openclaw?: Record<string, any>;
106
260
  _engine?: Record<string, any>;
107
261
  }
262
+ export interface AppManifestArtifact {
263
+ type: "image" | "binary" | "dir";
264
+ path: string;
265
+ }
108
266
  export interface AppManifest {
109
267
  id: string;
110
268
  installed_at: string;
111
269
  source?: string;
112
270
  spec_hash?: string;
271
+ install_mode?: "app-dir" | "instance-dir";
272
+ artifacts?: AppManifestArtifact[];
113
273
  }
@@ -0,0 +1,15 @@
1
+ type ExecFileSyncLike = (command: string, args?: readonly string[], options?: Record<string, any>) => string | Buffer;
2
+ type ExistsSyncLike = (path: string) => boolean;
3
+ export interface ResolveDockerHostOptions {
4
+ jishuHome: string;
5
+ colimaProfile?: string;
6
+ env?: NodeJS.ProcessEnv;
7
+ platform?: NodeJS.Platform | string;
8
+ execFileSyncImpl?: ExecFileSyncLike;
9
+ existsSyncImpl?: ExistsSyncLike;
10
+ }
11
+ export declare function managedColimaSocketPath(jishuHome: string, colimaProfile?: string): string;
12
+ export declare function managedColimaDockerHost(jishuHome: string, colimaProfile?: string): string;
13
+ export declare function resolveDockerHost(options: ResolveDockerHostOptions): string | undefined;
14
+ export declare function buildDockerClientEnv(options: ResolveDockerHostOptions): NodeJS.ProcessEnv;
15
+ export {};
@@ -0,0 +1,64 @@
1
+ import { execFileSync } from "child_process";
2
+ import { existsSync } from "fs";
3
+ import { join } from "path";
4
+ export function managedColimaSocketPath(jishuHome, colimaProfile = "jishushell") {
5
+ return join(jishuHome, "colima", colimaProfile, "docker.sock");
6
+ }
7
+ export function managedColimaDockerHost(jishuHome, colimaProfile = "jishushell") {
8
+ return `unix://${managedColimaSocketPath(jishuHome, colimaProfile)}`;
9
+ }
10
+ function resolveDockerHostFromCurrentContext(env, execFileSyncImpl) {
11
+ const contextEnv = { ...env };
12
+ delete contextEnv.DOCKER_HOST;
13
+ try {
14
+ const contextName = String(execFileSyncImpl("docker", ["context", "show"], {
15
+ encoding: "utf-8",
16
+ timeout: 3000,
17
+ env: contextEnv,
18
+ })).trim();
19
+ if (!contextName)
20
+ return undefined;
21
+ const raw = String(execFileSyncImpl("docker", ["context", "inspect", contextName], {
22
+ encoding: "utf-8",
23
+ timeout: 3000,
24
+ env: contextEnv,
25
+ }));
26
+ const parsed = JSON.parse(raw);
27
+ const host = parsed[0]?.Endpoints?.docker?.Host;
28
+ return typeof host === "string" && host.trim() ? host.trim() : undefined;
29
+ }
30
+ catch {
31
+ return undefined;
32
+ }
33
+ }
34
+ export function resolveDockerHost(options) {
35
+ const { jishuHome, colimaProfile = "jishushell", env = process.env, platform = process.platform, execFileSyncImpl = execFileSync, existsSyncImpl = existsSync, } = options;
36
+ const envHost = typeof env.DOCKER_HOST === "string" ? env.DOCKER_HOST.trim() : "";
37
+ const colimaSocket = managedColimaSocketPath(jishuHome, colimaProfile);
38
+ const colimaHost = managedColimaDockerHost(jishuHome, colimaProfile);
39
+ const contextHost = platform === "darwin"
40
+ ? resolveDockerHostFromCurrentContext(env, execFileSyncImpl)
41
+ : undefined;
42
+ if (platform === "darwin" && existsSyncImpl(colimaSocket)) {
43
+ return colimaHost;
44
+ }
45
+ if (envHost) {
46
+ if (platform === "darwin" && envHost === colimaHost) {
47
+ return contextHost;
48
+ }
49
+ return envHost;
50
+ }
51
+ if (contextHost)
52
+ return contextHost;
53
+ return undefined;
54
+ }
55
+ export function buildDockerClientEnv(options) {
56
+ const env = { ...(options.env ?? process.env) };
57
+ const dockerHost = resolveDockerHost(options);
58
+ if (dockerHost)
59
+ env.DOCKER_HOST = dockerHost;
60
+ else
61
+ delete env.DOCKER_HOST;
62
+ return env;
63
+ }
64
+ //# sourceMappingURL=docker-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-host.js","sourceRoot":"","sources":["../../src/utils/docker-host.ts"],"names":[],"mappings":"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"}
@@ -1887,8 +1887,25 @@ _ensure_nomad_hcl() {
1887
1887
  # LAN IP doesn't exist inside the Lima VM, causing "cannot assign requested
1888
1888
  # address" when Docker tries to bind to it.
1889
1889
  local loopback_iface="lo"
1890
+ local external_iface=""
1891
+ local external_host_network_block=""
1890
1892
  [[ "$OS" == "macos" ]] && loopback_iface="lo0"
1891
1893
 
1894
+ if [[ "$OS" == "macos" ]]; then
1895
+ external_iface="$(route -n get default 2>/dev/null | awk '/interface:/{print $2; exit}')"
1896
+ elif command -v ip >/dev/null 2>&1; then
1897
+ external_iface="$(ip route show default 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}')"
1898
+ fi
1899
+
1900
+ if [[ -n "$external_iface" && "$external_iface" != "$loopback_iface" ]]; then
1901
+ external_host_network_block=$(cat <<EOF
1902
+ host_network "external" {
1903
+ interface = "${external_iface}"
1904
+ }
1905
+ EOF
1906
+ )
1907
+ fi
1908
+
1892
1909
  cat > "$config_file" << NOMAD_HCL
1893
1910
  data_dir = "${nomad_data_dir}"
1894
1911
 
@@ -1912,6 +1929,7 @@ client {
1912
1929
  servers = ["127.0.0.1:4647"]
1913
1930
  network_interface = "${loopback_iface}"
1914
1931
  alloc_dir = "${nomad_alloc_dir}"
1932
+ ${external_host_network_block}
1915
1933
 
1916
1934
  drain_on_shutdown {
1917
1935
  deadline = "30s"
@@ -2705,7 +2723,13 @@ install_jishushell() {
2705
2723
  fi
2706
2724
  else
2707
2725
  log_detail "[$(date '+%H:%M:%S')] ${npm_bin} install -g ${jishushell_pkg_spec} ${npm_registry_args[*]:-}"
2708
- if ! log_cmd "$npm_bin" install -g "${jishushell_pkg_spec}" "${npm_registry_args[@]}"; then
2726
+ if [[ ${#npm_registry_args[@]} -gt 0 ]]; then
2727
+ if ! log_cmd "$npm_bin" install -g "${jishushell_pkg_spec}" "${npm_registry_args[@]}"; then
2728
+ unset JISHU_RUNNING_IN_INSTALLER
2729
+ ui_error "npm install -g ${jishushell_pkg_spec} failed"
2730
+ return 1
2731
+ fi
2732
+ elif ! log_cmd "$npm_bin" install -g "${jishushell_pkg_spec}"; then
2709
2733
  unset JISHU_RUNNING_IN_INSTALLER
2710
2734
  ui_error "npm install -g ${jishushell_pkg_spec} failed"
2711
2735
  return 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jishushell",
3
- "version": "0.4.17",
3
+ "version": "0.4.24",
4
4
  "description": "JishuShell - Multi-Agent Framework Management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,8 +10,11 @@
10
10
  "dist/",
11
11
  "public/",
12
12
  "scripts/",
13
+ "apps/",
13
14
  "install/",
15
+ "templates/",
14
16
  "Dockerfile.openclaw-slim",
17
+ "Dockerfile.hermes-slim",
15
18
  "openclaw-entry.sh",
16
19
  "INSTALL-NOTICE",
17
20
  "THIRD-PARTY-NOTICES"
@@ -29,22 +32,29 @@
29
32
  "test:e2e:real:verbose": "npm run build:backend && vitest run --config vitest.e2e-real.config.ts --reporter=verbose",
30
33
  "test:watch": "vitest",
31
34
  "test:coverage": "vitest run --coverage",
32
- "test:ci": "npm run build:backend && vitest run --coverage && cd frontend && npm install && npm run test",
35
+ "test:ci": "npm run check:contracts && npm run build:backend && vitest run --coverage && cd frontend && npm install && npm run test",
33
36
  "test:ci:full": "npm run test:ci && vitest run --config vitest.e2e-real.config.ts",
34
37
  "prepublishOnly": "npm run build && chmod +x dist/cli.js",
35
38
  "postinstall": "bash install/post-install.sh",
36
39
  "preuninstall": "bash install/post-uninstall.sh",
37
40
  "prepare": "git config core.hooksPath .githooks 2>/dev/null || true",
38
41
  "build:pack": "npm run build && npm pack",
42
+ "check:contracts": "node --experimental-strip-types scripts/check-adapter-isolation.ts",
39
43
  "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"
40
44
  },
41
45
  "engines": {
42
46
  "node": ">=22"
43
47
  },
44
48
  "keywords": [
49
+ "mac mini",
50
+ "mac studio",
51
+ "nvidia jetson",
52
+ "nvidia dgx spark",
45
53
  "raspberry-pi",
46
- "server-panel",
47
- "openclaw"
54
+ "RK3588",
55
+ "openclaw",
56
+ "hermes-agent",
57
+ "ollama"
48
58
  ],
49
59
  "license": "Apache-2.0",
50
60
  "dependencies": {
@@ -0,0 +1 @@
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};
@@ -0,0 +1 @@
1
+ import{j as r,ax as J}from"./index-DQsM6Joa.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};
@@ -0,0 +1,4 @@
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};
@@ -0,0 +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-DQsM6Joa.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};