@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.
- package/lib/client.js +59 -9
- 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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
}
|