@genkaku/dsh-user-plugin 0.1.19 → 0.1.21

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 (2) hide show
  1. package/lib/client.js +220 -27
  2. package/package.json +3 -3
package/lib/client.js CHANGED
@@ -30,6 +30,7 @@ __export(index_exports, {
30
30
  });
31
31
  module.exports = __toCommonJS(index_exports);
32
32
  var import_react = require("react");
33
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
33
34
 
34
35
  // src/client/assets/genkaku-mark-b.png
35
36
  var genkaku_mark_b_default = "data:image/png;base64,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";
@@ -42,6 +43,8 @@ var import_jsx_runtime = require("react/jsx-runtime");
42
43
  var PANEL_ID = "genkaku-user";
43
44
  var CANDIDATE_PORTS = [47821, 47822, 47823, 47824, 47825, 47826];
44
45
  var originOf = (port) => `http://127.0.0.1:${port}`;
46
+ var ZH = typeof navigator !== "undefined" && /^zh/i.test(navigator.language);
47
+ var t = (en, zh) => ZH ? zh : en;
45
48
  var inject = ["slots"];
46
49
  function Icon({ size = 16 }) {
47
50
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", width: size, height: size }, "aria-hidden": "true", children: [
@@ -78,6 +81,7 @@ function Icon({ size = 16 }) {
78
81
  var row = { display: "flex", justifyContent: "space-between", gap: 12, padding: "6px 0" };
79
82
  var dim = { opacity: 0.6 };
80
83
  var box = { border: "1px solid rgba(255,255,255,0.12)", borderRadius: 10, padding: 12, marginTop: 12 };
84
+ var caption = { fontSize: 11, textTransform: "uppercase", letterSpacing: 1, opacity: 0.6, marginBottom: 6 };
81
85
  function useScrollThumb() {
82
86
  const [node, setNode] = (0, import_react.useState)(null);
83
87
  const nodeRef = (0, import_react.useRef)(null);
@@ -119,6 +123,10 @@ function useScrollThumb() {
119
123
  function Page() {
120
124
  const [status, setStatus] = (0, import_react.useState)(null);
121
125
  const [error, setError] = (0, import_react.useState)(null);
126
+ const [notice, setNotice] = (0, import_react.useState)(null);
127
+ const [busy, setBusy] = (0, import_react.useState)(null);
128
+ const [newWorker, setNewWorker] = (0, import_react.useState)("");
129
+ const originRef = (0, import_react.useRef)(null);
122
130
  const models = useScrollThumb();
123
131
  const load = (0, import_react.useCallback)(async () => {
124
132
  for (const port of CANDIDATE_PORTS) {
@@ -130,6 +138,7 @@ function Page() {
130
138
  if (!res.ok) continue;
131
139
  const doc = await res.json();
132
140
  if (doc.role !== "user") continue;
141
+ originRef.current = originOf(port);
133
142
  setStatus(doc);
134
143
  setError(null);
135
144
  return;
@@ -145,6 +154,62 @@ function Page() {
145
154
  }, 5e3);
146
155
  return () => clearInterval(timer);
147
156
  }, [load]);
157
+ const post = (0, import_react.useCallback)(async (path, body) => {
158
+ const origin = originRef.current;
159
+ if (origin == null) throw new Error(t("Bridge not reached yet.", "\u5C1A\u672A\u9023\u4E0A bridge\u3002"));
160
+ const res = await fetch(`${origin}${path}`, {
161
+ method: "POST",
162
+ headers: { "content-type": "application/json" },
163
+ body: JSON.stringify(body)
164
+ });
165
+ const doc = await res.json().catch(() => null);
166
+ if (!res.ok) throw new Error(doc?.error?.message ?? `HTTP ${res.status}`);
167
+ }, []);
168
+ const saveWorkers = (0, import_react.useCallback)(async (next) => {
169
+ setBusy("workers");
170
+ setNotice(null);
171
+ try {
172
+ await post("/genkaku/settings", { workers: next });
173
+ setNotice(t("Saved. The bridge is restarting with the new worker list.", "\u5DF2\u5132\u5B58\uFF0Cbridge \u6B63\u4EE5\u65B0\u7684 worker \u6E05\u55AE\u91CD\u65B0\u555F\u52D5\u3002"));
174
+ setTimeout(() => {
175
+ void load();
176
+ }, 2500);
177
+ } catch (e) {
178
+ setNotice(e instanceof Error ? e.message : String(e));
179
+ } finally {
180
+ setBusy(null);
181
+ }
182
+ }, [load, post]);
183
+ const setSettle = (0, import_react.useCallback)(async (next) => {
184
+ setBusy("settle");
185
+ setNotice(null);
186
+ try {
187
+ await post("/genkaku/settings", { settle: next });
188
+ setNotice(next ? t("Escrow payments enabled \u2014 restarting the bridge.", "\u5DF2\u958B\u555F\u6258\u7BA1\u4ED8\u6B3E\uFF0Cbridge \u6B63\u5728\u91CD\u65B0\u555F\u52D5\u3002") : t("Escrow payments disabled \u2014 free/dev sessions only. Restarting the bridge.", "\u5DF2\u95DC\u9589\u6258\u7BA1\u4ED8\u6B3E\uFF0C\u50C5\u9650\u514D\u8CBB/\u958B\u767C\u7528 session\u3002bridge \u6B63\u5728\u91CD\u65B0\u555F\u52D5\u3002"));
189
+ setTimeout(() => {
190
+ void load();
191
+ }, 2500);
192
+ } catch (e) {
193
+ setNotice(e instanceof Error ? e.message : String(e));
194
+ } finally {
195
+ setBusy(null);
196
+ }
197
+ }, [load, post]);
198
+ const refreshNetwork = (0, import_react.useCallback)(async () => {
199
+ setBusy("refresh");
200
+ setNotice(null);
201
+ try {
202
+ await post("/genkaku/settings", { refresh: true });
203
+ setNotice(t("Re-scanning the directory and the seed.", "\u6B63\u5728\u91CD\u65B0\u6383\u63CF\u93C8\u4E0A\u76EE\u9304\u8207 seed\u3002"));
204
+ setTimeout(() => {
205
+ void load();
206
+ }, 600);
207
+ } catch (e) {
208
+ setNotice(e instanceof Error ? e.message : String(e));
209
+ } finally {
210
+ setBusy(null);
211
+ }
212
+ }, [load, post]);
148
213
  if (error != null) {
149
214
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16 }, children: [
150
215
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0 }, children: "GenKaKu network" }),
@@ -157,49 +222,177 @@ function Page() {
157
222
  }
158
223
  if (status == null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: 16, ...dim }, children: "Loading worker status\u2026" });
159
224
  const offers = status.offers ?? [];
160
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16, maxWidth: 720 }, children: [
225
+ const price = (micro) => {
226
+ const n = Number(micro);
227
+ if (!Number.isFinite(n)) return "\u2014";
228
+ return n === 0 ? "free" : `${(n / 1e6).toFixed(2)} USDC`;
229
+ };
230
+ const eth = (wei) => {
231
+ const n = Number(wei);
232
+ return Number.isFinite(n) ? `${(n / 1e18).toFixed(4)} ETH` : "\u2014";
233
+ };
234
+ const usdc = (micro) => {
235
+ const n = Number(micro);
236
+ return Number.isFinite(n) ? `${(n / 1e6).toFixed(2)} USDC` : "\u2014";
237
+ };
238
+ const short = (addr) => addr == null || addr.length < 12 ? addr ?? "\u2014" : `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
239
+ const wallets = new Set(offers.map((o) => o.offer?.workerWallet).filter((w) => typeof w === "string" && w !== ""));
240
+ const workerCount = wallets.size > 0 ? wallets.size : (status.workers ?? []).length;
241
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16, maxWidth: 760 }, children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
243
+ .gk-net-wrap { position: relative; padding-right: 12px; }
244
+ .gk-net-models { max-height: min(380px, 48vh); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
245
+ .gk-net-models::-webkit-scrollbar { display: none; }
246
+ .gk-net-rail { position: absolute; top: 2px; bottom: 2px; right: 2px; width: 8px; border-radius: 4px; background: rgba(127,137,153,.16); cursor: pointer; }
247
+ .gk-net-thumb { position: absolute; left: 0; width: 8px; min-height: 16px; border-radius: 4px; background: rgba(127,137,153,.7); }
248
+ .gk-net-rail:hover .gk-net-thumb { background: rgba(127,137,153,.9); }
249
+ .gk-net-row { display: grid; grid-template-columns: minmax(0, 1fr) 92px 116px; gap: 10px; align-items: center; padding: 7px 0; border-top: 0.5px solid rgba(127,137,153,.18); }
250
+ .gk-net-row:first-child { border-top: none; }
251
+ ` }),
161
252
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0 }, children: "GenKaKu network" }),
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, marginTop: 4 }, children: status.role ?? "unknown role" }),
253
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...dim, marginTop: 4 }, children: [
254
+ "user \xB7 ",
255
+ status.env ?? "base-sepolia"
256
+ ] }),
257
+ notice != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...box, fontSize: 13 }, children: notice }),
163
258
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
164
259
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
165
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Peer" }),
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: status.peerId ?? "\u2014" })
260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Wallet", "\u9322\u5305") }),
261
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 8 }, children: [
262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { title: status.wallet, children: short(status.wallet) }),
263
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
264
+ import_dsh_client_ui_primitives.Button,
265
+ {
266
+ variant: "ghost",
267
+ size: "sm",
268
+ onClick: () => {
269
+ if (status.wallet != null && navigator.clipboard != null) {
270
+ void navigator.clipboard.writeText(status.wallet);
271
+ setNotice(t("Wallet address copied.", "\u5DF2\u8907\u88FD\u9322\u5305\u4F4D\u5740\u3002"));
272
+ }
273
+ },
274
+ children: t("copy", "\u8907\u88FD")
275
+ }
276
+ )
277
+ ] })
167
278
  ] }),
168
279
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
169
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Sessions served" }),
170
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.sessions ?? 0 })
280
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Balance" }),
281
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
282
+ eth(status.balances?.eth),
283
+ " \xB7 ",
284
+ usdc(status.balances?.usdc)
285
+ ] })
171
286
  ] }),
172
287
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
173
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Published on-chain" }),
174
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.published === true ? "yes" : "no" })
288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Payments" }),
289
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.settle === true ? "escrow enabled" : "free / dev" })
175
290
  ] }),
176
291
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Addresses" }),
178
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: (status.peerAddrs ?? []).length })
292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Workers discovered" }),
293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: workerCount })
294
+ ] }),
295
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
296
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Models offered" }),
297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: offers.length })
179
298
  ] })
180
299
  ] }),
181
300
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
182
301
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: "Models on the network" }),
183
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
184
- .gk-net-wrap { position: relative; padding-right: 12px; }
185
- .gk-net-models { max-height: min(360px, 45vh); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
186
- .gk-net-models::-webkit-scrollbar { display: none; }
187
- .gk-net-rail { position: absolute; top: 2px; bottom: 2px; right: 2px; width: 8px; border-radius: 4px; background: rgba(127,137,153,.16); cursor: pointer; }
188
- .gk-net-thumb { position: absolute; left: 0; width: 8px; min-height: 16px; border-radius: 4px; background: rgba(127,137,153,.7); }
189
- .gk-net-rail:hover .gk-net-thumb { background: rgba(127,137,153,.9); }
190
- ` }),
191
302
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "gk-net-wrap", children: [
192
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-net-models", ref: models.attach, onScroll: models.update, children: offers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { ...dim, marginBottom: 0 }, children: "Nothing offered yet. The worker auto-lists local Ollama models on start." }) : offers.map((offer, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
193
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: offer.model ?? "\u2014" }),
194
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: dim, children: [
195
- offer.pricePerHour ?? "?",
196
- " / hour",
197
- offer.tier === "chat" ? " \xB7 not for agents" : "",
198
- offer.addr != null && status.transports?.[offer.addr] === "relay" ? " \xB7 via seed VM" : offer.addr != null && status.transports?.[offer.addr] === "direct" ? " \xB7 direct" : ""
199
- ] })
200
- ] }, `${offer.model ?? i}`)) }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-net-models", ref: models.attach, onScroll: models.update, children: offers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { ...dim, marginBottom: 0 }, children: "Nothing offered yet. A worker lists its local Ollama models on start." }) : offers.map((entry, i) => {
304
+ const offer = entry.offer ?? {};
305
+ const transport = entry.addr == null ? null : status.transports?.[entry.addr];
306
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "gk-net-row", children: [
307
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
308
+ offer.model ?? "model name missing",
309
+ offer.tier === "chat" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, fontSize: 11, marginLeft: 8 }, children: "not for agents" }) : offer.tier != null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, fontSize: 11, marginLeft: 8 }, children: offer.tier }) : null
310
+ ] }),
311
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, textAlign: "right", fontSize: 12 }, children: offer.workerName ?? "\u2014" }),
312
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { textAlign: "right", fontSize: 12 }, children: [
313
+ price(offer.pricePerHour),
314
+ " ",
315
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: transport === "relay" ? "\xB7 via seed VM" : transport === "direct" ? "\xB7 direct" : "" })
316
+ ] })
317
+ ] }, `${entry.addr ?? ""}:${offer.model ?? i}`);
318
+ }) }),
201
319
  models.thumb != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-net-rail", "aria-hidden": "true", onPointerDown: (e) => models.jump(e), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-net-thumb", style: { top: `${models.thumb.top}%`, height: `${models.thumb.height}%` } }) })
202
320
  ] })
321
+ ] }),
322
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
323
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: caption, children: t("Settings", "\u8A2D\u5B9A") }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
325
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("Escrow payments", "\u6258\u7BA1\u4ED8\u6B3E") }),
326
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
327
+ import_dsh_client_ui_primitives.Switch,
328
+ {
329
+ checked: status.settle === true,
330
+ disabled: busy === "settle",
331
+ label: t("Escrow payments", "\u6258\u7BA1\u4ED8\u6B3E"),
332
+ onChange: (next) => {
333
+ void setSettle(next);
334
+ }
335
+ }
336
+ )
337
+ ] }),
338
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12 }, children: status.settle === true ? t(
339
+ "Each session opens a USDC escrow on Base Sepolia and settles per started minute. Needs ETH for gas and USDC in the wallet above.",
340
+ "\u6BCF\u500B session \u6703\u5728 Base Sepolia \u958B\u6258\u7BA1\u4E26\u4EE5\u5DF2\u958B\u59CB\u5206\u9418\u7D50\u7B97\u3002\u4E0A\u65B9\u9322\u5305\u9700\u8981\u6709 ETH \u4ED8 gas\u3001\u4EE5\u53CA USDC\u3002"
341
+ ) : t(
342
+ "Sessions are free and nothing is signed on-chain. Turn this back on before using the network against real workers.",
343
+ "\u76EE\u524D session \u514D\u8CBB\u3001\u93C8\u4E0A\u4E0D\u7C3D\u4EFB\u4F55\u6771\u897F\u3002\u5C0D\u771F\u5BE6 worker \u4F7F\u7528\u524D\u8ACB\u91CD\u65B0\u958B\u555F\u3002"
344
+ ) }),
345
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...caption, marginTop: 16 }, children: t("Manual workers", "\u624B\u52D5 worker") }),
346
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginBottom: 6 }, children: t(
347
+ "Optional multiaddrs pinned to this profile. Discovery through the on-chain directory and the seed still runs.",
348
+ "\u53EF\u9078\uFF1A\u56FA\u5B9A\u5728\u6B64 profile \u7684 worker multiaddr\u3002\u93C8\u4E0A\u76EE\u9304\u8207 seed \u7684\u63A2\u7D22\u4ECD\u6703\u81EA\u52D5\u57F7\u884C\u3002"
349
+ ) }),
350
+ (status.manualWorkers ?? []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12 }, children: t("None pinned \u2014 using discovery only.", "\u6C92\u6709\u56FA\u5B9A\u9805\u76EE\uFF0C\u53EA\u7528\u81EA\u52D5\u63A2\u7D22\u3002") }) : (status.manualWorkers ?? []).map((addr) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, gap: 8 }, children: [
351
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { style: { fontSize: 12, wordBreak: "break-all" }, children: addr }),
352
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
353
+ import_dsh_client_ui_primitives.Button,
354
+ {
355
+ variant: "ghost",
356
+ size: "sm",
357
+ disabled: busy === "workers",
358
+ onClick: () => {
359
+ void saveWorkers((status.manualWorkers ?? []).filter((w) => w !== addr));
360
+ },
361
+ children: t("remove", "\u79FB\u9664")
362
+ }
363
+ )
364
+ ] }, addr)),
365
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 8 }, children: [
366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
367
+ import_dsh_client_ui_primitives.Input,
368
+ {
369
+ value: newWorker,
370
+ placeholder: "/ip4/1.2.3.4/tcp/4001/p2p/12D3Koo\u2026",
371
+ "aria-label": t("Worker multiaddr", "Worker multiaddr"),
372
+ onChange: (e) => setNewWorker(e.target.value)
373
+ }
374
+ ),
375
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
376
+ import_dsh_client_ui_primitives.Button,
377
+ {
378
+ variant: "outline",
379
+ size: "sm",
380
+ disabled: busy === "workers" || !newWorker.trim().startsWith("/"),
381
+ onClick: () => {
382
+ const addr = newWorker.trim();
383
+ if (!addr.startsWith("/")) return;
384
+ void saveWorkers([...status.manualWorkers ?? [], addr]).then(() => setNewWorker(""));
385
+ },
386
+ children: t("Add", "\u65B0\u589E")
387
+ }
388
+ )
389
+ ] }),
390
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, marginTop: 14 }, children: [
391
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled: busy === "refresh", onClick: () => {
392
+ void refreshNetwork();
393
+ }, children: busy === "refresh" ? t("Refreshing\u2026", "\u91CD\u65B0\u6383\u63CF\u4E2D\u2026") : t("Refresh network", "\u91CD\u65B0\u6383\u63CF\u7DB2\u8DEF") }),
394
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, fontSize: 12 }, children: t("Re-reads the directory and the seed now.", "\u7ACB\u5373\u91CD\u8B80\u93C8\u4E0A\u76EE\u9304\u8207 seed\u3002") })
395
+ ] })
203
396
  ] })
204
397
  ] });
205
398
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genkaku/dsh-user-plugin",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Buy peer-to-peer inference from the GenKaKu network",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,8 +39,8 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@deepseek-ai/dsh-llm": "0.2.2-rc.1",
42
- "@genkaku/dsh-runtime": "0.1.19",
43
- "@genkaku/protocol": "0.1.13"
42
+ "@genkaku/dsh-runtime": "0.1.21",
43
+ "@genkaku/protocol": "0.1.14"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@deepseek-ai/cordis": "^4.1.0",