@genkaku/dsh-worker-plugin 0.1.22 → 0.1.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.
- package/lib/client.js +116 -56
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -92,26 +92,36 @@ var PANEL_CSS = `
|
|
|
92
92
|
.gk-pull { width: 260px; max-width: 100%; }
|
|
93
93
|
.gk-muted { color: var(--dsw-alias-label-tertiary); font-size: 12px; }
|
|
94
94
|
/* The panel can hold every model Ollama has (two dozen is normal). A bounded
|
|
95
|
-
list
|
|
96
|
-
|
|
95
|
+
list keeps the download box, Save and the Worker section reachable.
|
|
96
|
+
macOS auto-hides native scrollbars (and Chromium screenshots never paint
|
|
97
|
+
them), so the bar is drawn by us: always visible, and click-to-jump. */
|
|
98
|
+
.gk-models-wrap { position: relative; padding-right: 12px; }
|
|
97
99
|
.gk-models {
|
|
98
100
|
max-height: min(420px, 45vh);
|
|
99
101
|
overflow-y: auto;
|
|
100
102
|
overscroll-behavior: contain;
|
|
101
|
-
|
|
102
|
-
scrollbar-width: thin;
|
|
103
|
+
scrollbar-width: none;
|
|
103
104
|
}
|
|
104
|
-
.gk-models::-webkit-scrollbar {
|
|
105
|
-
.gk-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
.gk-models::-webkit-scrollbar { display: none; }
|
|
106
|
+
.gk-rail {
|
|
107
|
+
position: absolute;
|
|
108
|
+
top: 2px;
|
|
109
|
+
bottom: 2px;
|
|
110
|
+
right: 2px;
|
|
111
|
+
width: 8px;
|
|
112
|
+
border-radius: 4px;
|
|
113
|
+
background: rgba(127,137,153,.16);
|
|
114
|
+
cursor: pointer;
|
|
111
115
|
}
|
|
112
|
-
.gk-
|
|
113
|
-
|
|
116
|
+
.gk-thumb {
|
|
117
|
+
position: absolute;
|
|
118
|
+
left: 0;
|
|
119
|
+
width: 8px;
|
|
120
|
+
min-height: 16px;
|
|
121
|
+
border-radius: 4px;
|
|
122
|
+
background: rgba(127,137,153,.7);
|
|
114
123
|
}
|
|
124
|
+
.gk-rail:hover .gk-thumb { background: rgba(127,137,153,.9); }
|
|
115
125
|
`;
|
|
116
126
|
function Icon({ size = 16 }) {
|
|
117
127
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", width: size, height: size }, "aria-hidden": "true", children: [
|
|
@@ -156,6 +166,44 @@ function seedDraft(status) {
|
|
|
156
166
|
function draftSignature(draft) {
|
|
157
167
|
return Object.entries(draft).map(([model, price]) => `${model}=${price}`).sort().join("|");
|
|
158
168
|
}
|
|
169
|
+
function useScrollThumb() {
|
|
170
|
+
const [node, setNode] = (0, import_react.useState)(null);
|
|
171
|
+
const nodeRef = (0, import_react.useRef)(null);
|
|
172
|
+
const [thumb, setThumb] = (0, import_react.useState)(null);
|
|
173
|
+
const attach = (0, import_react.useCallback)((next) => {
|
|
174
|
+
nodeRef.current = next;
|
|
175
|
+
setNode(next);
|
|
176
|
+
}, []);
|
|
177
|
+
const update = (0, import_react.useCallback)(() => {
|
|
178
|
+
const el = nodeRef.current;
|
|
179
|
+
if (el == null) return;
|
|
180
|
+
const ratio = el.scrollHeight > el.clientHeight + 1 ? el.clientHeight / el.scrollHeight : 1;
|
|
181
|
+
setThumb(ratio >= 1 ? null : { top: el.scrollTop / el.scrollHeight * 100, height: Math.max(ratio * 100, 8) });
|
|
182
|
+
}, []);
|
|
183
|
+
(0, import_react.useEffect)(() => {
|
|
184
|
+
if (node == null) return;
|
|
185
|
+
update();
|
|
186
|
+
node.addEventListener("scroll", update, { passive: true });
|
|
187
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
188
|
+
ro?.observe(node);
|
|
189
|
+
const mo = typeof MutationObserver === "undefined" ? null : new MutationObserver(update);
|
|
190
|
+
mo?.observe(node, { childList: true, subtree: true });
|
|
191
|
+
return () => {
|
|
192
|
+
node.removeEventListener("scroll", update);
|
|
193
|
+
ro?.disconnect();
|
|
194
|
+
mo?.disconnect();
|
|
195
|
+
};
|
|
196
|
+
}, [node, update]);
|
|
197
|
+
const jump = (0, import_react.useCallback)((event) => {
|
|
198
|
+
const el = nodeRef.current;
|
|
199
|
+
const rail = event.currentTarget;
|
|
200
|
+
if (el == null || rail == null) return;
|
|
201
|
+
const rect = rail.getBoundingClientRect();
|
|
202
|
+
if (rect.height <= 0) return;
|
|
203
|
+
el.scrollTop = Math.max(0, (event.clientY - rect.top) / rect.height) * el.scrollHeight;
|
|
204
|
+
}, []);
|
|
205
|
+
return { attach, thumb, update, jump };
|
|
206
|
+
}
|
|
159
207
|
function Section({ title, children }) {
|
|
160
208
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
|
|
161
209
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: caption, children: title }),
|
|
@@ -173,6 +221,7 @@ function Page() {
|
|
|
173
221
|
const [pullModel, setPullModel] = (0, import_react.useState)("");
|
|
174
222
|
const [pull, setPull] = (0, import_react.useState)(null);
|
|
175
223
|
const seeded = (0, import_react.useRef)(false);
|
|
224
|
+
const models = useScrollThumb();
|
|
176
225
|
const [origin, setOrigin] = (0, import_react.useState)(originOf(CANDIDATE_PORTS[0]));
|
|
177
226
|
const originRef = (0, import_react.useRef)(origin);
|
|
178
227
|
originRef.current = origin;
|
|
@@ -472,53 +521,64 @@ function Page() {
|
|
|
472
521
|
"\u672A\u52FE\u9078\u7684\u6A21\u578B\u4ECD\u7559\u5728\u672C\u6A5F\uFF0C\u4F46\u4E0D\u6703\u4E0A\u67B6\u3002\u50F9\u683C\u70BA\u6BCF\u5C0F\u6642 USDC\uFF1B0 \u8868\u793A\u514D\u8CBB\u3002"
|
|
473
522
|
) }),
|
|
474
523
|
names.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: dim, children: t("No local models yet. Download one below.", "\u672C\u6A5F\u9084\u6C92\u6709\u6A21\u578B\uFF0C\u53EF\u5728\u4E0B\u65B9\u4E0B\u8F09\u3002") }),
|
|
475
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
480
|
-
"input",
|
|
481
|
-
{
|
|
482
|
-
type: "checkbox",
|
|
483
|
-
checked: on,
|
|
484
|
-
"aria-label": name,
|
|
485
|
-
onChange: () => {
|
|
486
|
-
toggleOffer(name);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
),
|
|
490
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
491
|
-
name,
|
|
492
|
-
tier !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, fontSize: 11, marginLeft: 8 }, children: tier === "chat" ? t("not for agents", "\u4E0D\u9069\u7528\u65BC agent") : tier })
|
|
493
|
-
] }),
|
|
494
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", style: { textAlign: "right" }, children: gb(sizeOf.get(name)) }),
|
|
495
|
-
on ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "gk-models-wrap", children: [
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-models", ref: models.attach, onScroll: models.update, children: names.map((name) => {
|
|
526
|
+
const on = name in offered;
|
|
527
|
+
const tier = tierOf.get(name);
|
|
528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "gk-row", children: [
|
|
496
529
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
497
|
-
|
|
530
|
+
"input",
|
|
498
531
|
{
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
532
|
+
type: "checkbox",
|
|
533
|
+
checked: on,
|
|
534
|
+
"aria-label": name,
|
|
535
|
+
onChange: () => {
|
|
536
|
+
toggleOffer(name);
|
|
537
|
+
}
|
|
504
538
|
}
|
|
505
539
|
),
|
|
506
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
{
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
541
|
+
name,
|
|
542
|
+
tier !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...dim, fontSize: 11, marginLeft: 8 }, children: tier === "chat" ? t("not for agents", "\u4E0D\u9069\u7528\u65BC agent") : tier })
|
|
543
|
+
] }),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", style: { textAlign: "right" }, children: gb(sizeOf.get(name)) }),
|
|
545
|
+
on ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
547
|
+
import_dsh_client_ui_primitives.Input,
|
|
548
|
+
{
|
|
549
|
+
className: "gk-price",
|
|
550
|
+
value: offered[name] ?? "",
|
|
551
|
+
inputMode: "decimal",
|
|
552
|
+
"aria-label": t(`Price per hour for ${name}`, `${name} \u6BCF\u5C0F\u6642\u50F9\u683C`),
|
|
553
|
+
onChange: (e) => setDraft({ ...draft ?? {}, [name]: e.target.value })
|
|
554
|
+
}
|
|
555
|
+
),
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", children: "/h" })
|
|
557
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
558
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
559
|
+
import_dsh_client_ui_primitives.Button,
|
|
560
|
+
{
|
|
561
|
+
variant: "ghost",
|
|
562
|
+
size: "sm",
|
|
563
|
+
disabled: busy === `remove:${name}`,
|
|
564
|
+
onClick: () => {
|
|
565
|
+
void removeModel(name);
|
|
566
|
+
},
|
|
567
|
+
children: t("delete", "\u522A\u9664")
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
] }, name);
|
|
571
|
+
}) }),
|
|
572
|
+
models.thumb != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
573
|
+
"div",
|
|
574
|
+
{
|
|
575
|
+
className: "gk-rail",
|
|
576
|
+
"aria-hidden": "true",
|
|
577
|
+
onPointerDown: (e) => models.jump(e),
|
|
578
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "gk-thumb", style: { top: `${models.thumb.top}%`, height: `${models.thumb.height}%` } })
|
|
579
|
+
}
|
|
580
|
+
)
|
|
581
|
+
] }),
|
|
522
582
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, justifyContent: "flex-start", gap: 8, marginTop: 12 }, children: [
|
|
523
583
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
524
584
|
import_dsh_client_ui_primitives.Input,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genkaku/dsh-worker-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "Share this machine's Ollama models on the GenKaKu network",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@genkaku/dsh-runtime": "0.1.
|
|
41
|
+
"@genkaku/dsh-runtime": "0.1.20",
|
|
42
42
|
"@genkaku/protocol": "0.1.13"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|