@genkaku/dsh-worker-plugin 0.1.14 → 0.1.16

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 +67 -24
  2. package/package.json +6 -3
package/lib/client.js CHANGED
@@ -38,10 +38,8 @@ var genkaku_mark_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK4AAA
38
38
  // src/client/index.tsx
39
39
  var import_jsx_runtime = require("react/jsx-runtime");
40
40
  var PANEL_ID = "genkaku-worker";
41
- var ORIGIN = "http://127.0.0.1:47821";
42
- var STATUS_URL = `${ORIGIN}/genkaku/status`;
43
- var OLLAMA_URL = `${ORIGIN}/genkaku/ollama`;
44
- var DASHBOARD_URL = `${ORIGIN}/genkaku`;
41
+ var CANDIDATE_PORTS = [47821, 47822, 47823, 47824, 47825, 47826];
42
+ var originOf = (port) => `http://127.0.0.1:${port}`;
45
43
  var inject = ["slots"];
46
44
  var ZH = typeof navigator !== "undefined" && /^zh/i.test(navigator.language);
47
45
  var t = (en, zh) => ZH ? zh : en;
@@ -162,24 +160,49 @@ function Page() {
162
160
  const [pullModel, setPullModel] = (0, import_react.useState)("");
163
161
  const [pull, setPull] = (0, import_react.useState)(null);
164
162
  const seeded = (0, import_react.useRef)(false);
165
- const loadStatus = (0, import_react.useCallback)(async () => {
163
+ const [origin, setOrigin] = (0, import_react.useState)(originOf(CANDIDATE_PORTS[0]));
164
+ const originRef = (0, import_react.useRef)(origin);
165
+ originRef.current = origin;
166
+ const probe = (0, import_react.useCallback)(async (base) => {
166
167
  try {
167
- const res = await fetch(STATUS_URL, { cache: "no-store" });
168
- if (!res.ok) throw new Error(`status ${res.status}`);
169
- const next = await res.json();
170
- setStatus(next);
171
- setError(null);
172
- if (!seeded.current) {
173
- seeded.current = true;
174
- setDraft(seedDraft(next));
175
- }
176
- } catch (e) {
177
- setError(e instanceof Error ? e.message : String(e));
168
+ const res = await fetch(`${base}/genkaku/status`, { cache: "no-store", signal: AbortSignal.timeout(2500) });
169
+ if (!res.ok) return null;
170
+ const doc = await res.json();
171
+ return doc.role === "user" ? null : doc;
172
+ } catch {
173
+ return null;
178
174
  }
179
175
  }, []);
176
+ const loadStatus = (0, import_react.useCallback)(async () => {
177
+ let base = originRef.current;
178
+ let next = await probe(base);
179
+ if (next == null) {
180
+ for (const port of CANDIDATE_PORTS) {
181
+ const candidate = originOf(port);
182
+ if (candidate === base) continue;
183
+ const doc = await probe(candidate);
184
+ if (doc != null) {
185
+ base = candidate;
186
+ next = doc;
187
+ break;
188
+ }
189
+ }
190
+ }
191
+ if (next == null) {
192
+ setError(t("Worker status unreachable on 47821\u201347826.", "47821\u201347826 \u4E0A\u90FD\u627E\u4E0D\u5230 worker \u72C0\u614B\u670D\u52D9\u3002"));
193
+ return;
194
+ }
195
+ if (base !== originRef.current) setOrigin(base);
196
+ setStatus(next);
197
+ setError(null);
198
+ if (!seeded.current) {
199
+ seeded.current = true;
200
+ setDraft(seedDraft(next));
201
+ }
202
+ }, [probe]);
180
203
  const loadOllama = (0, import_react.useCallback)(async () => {
181
204
  try {
182
- const res = await fetch(OLLAMA_URL, { cache: "no-store" });
205
+ const res = await fetch(`${originRef.current}/genkaku/ollama`, { cache: "no-store" });
183
206
  if (!res.ok) throw new Error(`ollama ${res.status}`);
184
207
  setOllama(await res.json());
185
208
  } catch {
@@ -200,7 +223,7 @@ function Page() {
200
223
  };
201
224
  }, [loadStatus, loadOllama]);
202
225
  const post = (0, import_react.useCallback)(async (path, body) => {
203
- const res = await fetch(`${ORIGIN}${path}`, {
226
+ const res = await fetch(`${originRef.current}${path}`, {
204
227
  method: "POST",
205
228
  headers: { "content-type": "application/json" },
206
229
  body: JSON.stringify(body)
@@ -229,7 +252,7 @@ function Page() {
229
252
  setNotice(null);
230
253
  setPull({ status: t("starting", "\u958B\u59CB\u4E0B\u8F09") });
231
254
  try {
232
- const res = await fetch(`${ORIGIN}/genkaku/ollama/pull`, {
255
+ const res = await fetch(`${originRef.current}/genkaku/ollama/pull`, {
233
256
  method: "POST",
234
257
  headers: { "content-type": "application/json" },
235
258
  body: JSON.stringify({ model })
@@ -402,7 +425,7 @@ function Page() {
402
425
  import_dsh_client_ui_primitives.Switch,
403
426
  {
404
427
  checked: status.publishAddress === true,
405
- disabled: busy === "publish",
428
+ disabled: busy === "publish" || status.publishForced === true || status.reachable !== true && status.publishAddress !== true,
406
429
  label: t("Publish this worker on-chain", "\u5C07\u6B64 worker \u767C\u4F48\u5230\u93C8\u4E0A\u76EE\u9304"),
407
430
  onChange: (next) => {
408
431
  void setPublish(next);
@@ -411,9 +434,12 @@ function Page() {
411
434
  )
412
435
  ] }),
413
436
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginTop: 2 }, children: status.reachable !== true ? t(
414
- "This machine has no public address, so listing it would create an entry nobody can dial. Peers on the same network can still connect.",
415
- "\u9019\u53F0\u6A5F\u5668\u6C92\u6709\u516C\u7DB2\u4F4D\u5740\uFF0C\u767C\u4F48\u53EA\u6703\u7522\u751F\u4E00\u689D\u6C92\u4EBA\u9023\u5F97\u4E0A\u7684\u7D00\u9304\u3002\u540C\u7DB2\u6BB5\u7684 peer \u4ECD\u53EF\u9023\u7DDA\u3002"
416
- ) : status.publishAddress === true ? t(
437
+ "This machine has no public address, so this switch is off until it gets one: listing it would create an entry nobody can dial. Peers on the same network can still connect.",
438
+ "\u9019\u53F0\u6A5F\u5668\u6C92\u6709\u516C\u7DB2\u4F4D\u5740\uFF0C\u56E0\u6B64\u958B\u95DC\u76EE\u524D\u7121\u6CD5\u958B\u555F\uFF1A\u767C\u4F48\u53EA\u6703\u7522\u751F\u4E00\u689D\u6C92\u4EBA\u9023\u5F97\u4E0A\u7684\u7D00\u9304\u3002\u540C\u7DB2\u6BB5\u7684 peer \u4ECD\u53EF\u9023\u7DDA\u3002"
439
+ ) : status.publishForced === true ? t(
440
+ "Forced on by this profile (publishAddress), so it cannot be turned off here.",
441
+ "\u6B64 profile \u5DF2\u5F37\u5236\u958B\u555F\uFF08publishAddress\uFF09\uFF0C\u7121\u6CD5\u5728\u6B64\u95DC\u9589\u3002"
442
+ ) : status.published === true ? t(
417
443
  "Listed. Your public IP is written to the chain and stays readable forever, even after you turn this off.",
418
444
  "\u5DF2\u5217\u51FA\u3002\u4F60\u7684\u516C\u7DB2 IP \u6703\u5BEB\u9032\u93C8\u4E0A\uFF0C\u5373\u4F7F\u65E5\u5F8C\u95DC\u9589\uFF0C\u4ECD\u7136\u6C38\u4E45\u53EF\u8B80\u3002"
419
445
  ) : t(
@@ -523,6 +549,23 @@ function Page() {
523
549
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Wallet", "\u9322\u5305") }),
524
550
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: status.wallet ?? "\u2014" })
525
551
  ] }),
552
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
553
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Connection", "\u9023\u7DDA\u65B9\u5F0F") }),
554
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
555
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dot(status.transport === "direct") }),
556
+ status.transport === "direct" ? t("libp2p direct", "libp2p \u76F4\u9023") : status.transport === "relay" ? t("seed VM relay", "seed VM \u4E2D\u7E7C") : t("LAN only", "\u50C5\u9650\u540C\u7DB2\u6BB5")
557
+ ] })
558
+ ] }),
559
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginTop: 2 }, children: status.transport === "direct" ? t(
560
+ "Clients reach this worker directly over libp2p.",
561
+ "\u4F7F\u7528\u8005\u900F\u904E libp2p \u76F4\u63A5\u9023\u5230\u9019\u53F0 worker\u3002"
562
+ ) : status.transport === "relay" ? t(
563
+ "Direct dialing is not possible from the internet, so traffic is forwarded through the GenKaKu seed VM. Clients try a direct connection first, then fall back to the relay.",
564
+ "\u9019\u53F0\u6A5F\u5668\u7121\u6CD5\u88AB\u516C\u7DB2\u76F4\u9023\uFF0C\u56E0\u6B64\u6D41\u91CF\u6703\u7D93\u7531 GenKaKu seed VM \u8F49\u9001\u3002\u4F7F\u7528\u8005\u6703\u5148\u5617\u8A66\u76F4\u9023\uFF0C\u5931\u6557\u5F8C\u624D\u8D70\u4E2D\u7E7C\u3002"
565
+ ) : t(
566
+ "Only peers on the same network can connect. A relay appears once the seed VM is reachable.",
567
+ "\u76EE\u524D\u53EA\u6709\u540C\u7DB2\u6BB5\u7684 peer \u80FD\u9023\u7DDA\u3002\u9023\u4E0A seed VM \u5F8C\u6703\u81EA\u52D5\u53D6\u5F97\u4E2D\u7E7C\u4F4D\u5740\u3002"
568
+ ) }),
526
569
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
527
570
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Active sessions", "\u9032\u884C\u4E2D session") }),
528
571
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.activeSessions ?? 0 })
@@ -531,7 +574,7 @@ function Page() {
531
574
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Addresses", "\u4F4D\u5740\u6578") }),
532
575
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: (status.peerAddrs ?? []).length })
533
576
  ] }),
534
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...row, justifyContent: "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: DASHBOARD_URL, target: "_blank", rel: "noreferrer", style: { fontSize: 12 }, children: t("Open the full dashboard", "\u958B\u555F\u5B8C\u6574\u63A7\u5236\u53F0") }) })
577
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...row, justifyContent: "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `${origin}/genkaku`, target: "_blank", rel: "noreferrer", style: { fontSize: 12 }, children: t("Open the full dashboard", "\u958B\u555F\u5B8C\u6574\u63A7\u5236\u53F0") }) })
535
578
  ] })
536
579
  ] });
537
580
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genkaku/dsh-worker-plugin",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Share this machine's Ollama models on the GenKaKu network",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,8 +38,8 @@
38
38
  }
39
39
  },
40
40
  "dependencies": {
41
- "@genkaku/protocol": "0.1.10",
42
- "@genkaku/dsh-runtime": "0.1.13"
41
+ "@genkaku/dsh-runtime": "0.1.15",
42
+ "@genkaku/protocol": "0.1.11"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@deepseek-ai/cordis": "^4.1.0"
@@ -68,6 +68,9 @@
68
68
  "usdc",
69
69
  "base"
70
70
  ],
71
+ "engines": {
72
+ "node": ">=22"
73
+ },
71
74
  "scripts": {
72
75
  "build": "tsc -p tsconfig.json && node ../../scripts/build-client.mjs . @genkaku/dsh-worker-plugin",
73
76
  "typecheck": "tsc -p tsconfig.json --noEmit"