@genkaku/dsh-user-plugin 0.1.17 → 0.1.19

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 +59 -9
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -78,9 +78,48 @@ function Icon({ size = 16 }) {
78
78
  var row = { display: "flex", justifyContent: "space-between", gap: 12, padding: "6px 0" };
79
79
  var dim = { opacity: 0.6 };
80
80
  var box = { border: "1px solid rgba(255,255,255,0.12)", borderRadius: 10, padding: 12, marginTop: 12 };
81
+ function useScrollThumb() {
82
+ const [node, setNode] = (0, import_react.useState)(null);
83
+ const nodeRef = (0, import_react.useRef)(null);
84
+ const [thumb, setThumb] = (0, import_react.useState)(null);
85
+ const attach = (0, import_react.useCallback)((next) => {
86
+ nodeRef.current = next;
87
+ setNode(next);
88
+ }, []);
89
+ const update = (0, import_react.useCallback)(() => {
90
+ const el = nodeRef.current;
91
+ if (el == null) return;
92
+ const ratio = el.scrollHeight > el.clientHeight + 1 ? el.clientHeight / el.scrollHeight : 1;
93
+ setThumb(ratio >= 1 ? null : { top: el.scrollTop / el.scrollHeight * 100, height: Math.max(ratio * 100, 8) });
94
+ }, []);
95
+ (0, import_react.useEffect)(() => {
96
+ if (node == null) return;
97
+ update();
98
+ node.addEventListener("scroll", update, { passive: true });
99
+ const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
100
+ ro?.observe(node);
101
+ const mo = typeof MutationObserver === "undefined" ? null : new MutationObserver(update);
102
+ mo?.observe(node, { childList: true, subtree: true });
103
+ return () => {
104
+ node.removeEventListener("scroll", update);
105
+ ro?.disconnect();
106
+ mo?.disconnect();
107
+ };
108
+ }, [node, update]);
109
+ const jump = (0, import_react.useCallback)((event) => {
110
+ const el = nodeRef.current;
111
+ const rail = event.currentTarget;
112
+ if (el == null || rail == null) return;
113
+ const rect = rail.getBoundingClientRect();
114
+ if (rect.height <= 0) return;
115
+ el.scrollTop = Math.max(0, (event.clientY - rect.top) / rect.height) * el.scrollHeight;
116
+ }, []);
117
+ return { attach, thumb, update, jump };
118
+ }
81
119
  function Page() {
82
120
  const [status, setStatus] = (0, import_react.useState)(null);
83
121
  const [error, setError] = (0, import_react.useState)(null);
122
+ const models = useScrollThumb();
84
123
  const load = (0, import_react.useCallback)(async () => {
85
124
  for (const port of CANDIDATE_PORTS) {
86
125
  try {
@@ -141,15 +180,26 @@ function Page() {
141
180
  ] }),
142
181
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
143
182
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: "Models on the network" }),
144
- 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: [
145
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: offer.model ?? "\u2014" }),
146
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: dim, children: [
147
- offer.pricePerHour ?? "?",
148
- " / hour",
149
- offer.tier === "chat" ? " \xB7 not for agents" : "",
150
- offer.addr != null && status.transports?.[offer.addr] === "relay" ? " \xB7 via seed VM" : offer.addr != null && status.transports?.[offer.addr] === "direct" ? " \xB7 direct" : ""
151
- ] })
152
- ] }, `${offer.model ?? i}`))
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
+ /* @__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}`)) }),
201
+ 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
+ ] })
153
203
  ] })
154
204
  ] });
155
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genkaku/dsh-user-plugin",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Buy peer-to-peer inference from the GenKaKu network",
5
5
  "license": "MIT",
6
6
  "type": "module",