@genkaku/dsh-worker-plugin 0.1.21 → 0.1.23
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 +124 -43
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -91,6 +91,37 @@ var PANEL_CSS = `
|
|
|
91
91
|
.gk-price input { text-align: right; }
|
|
92
92
|
.gk-pull { width: 260px; max-width: 100%; }
|
|
93
93
|
.gk-muted { color: var(--dsw-alias-label-tertiary); font-size: 12px; }
|
|
94
|
+
/* The panel can hold every model Ollama has (two dozen is normal). A bounded
|
|
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; }
|
|
99
|
+
.gk-models {
|
|
100
|
+
max-height: min(420px, 45vh);
|
|
101
|
+
overflow-y: auto;
|
|
102
|
+
overscroll-behavior: contain;
|
|
103
|
+
scrollbar-width: none;
|
|
104
|
+
}
|
|
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;
|
|
115
|
+
}
|
|
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);
|
|
123
|
+
}
|
|
124
|
+
.gk-rail:hover .gk-thumb { background: rgba(127,137,153,.9); }
|
|
94
125
|
`;
|
|
95
126
|
function Icon({ size = 16 }) {
|
|
96
127
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", width: size, height: size }, "aria-hidden": "true", children: [
|
|
@@ -135,6 +166,44 @@ function seedDraft(status) {
|
|
|
135
166
|
function draftSignature(draft) {
|
|
136
167
|
return Object.entries(draft).map(([model, price]) => `${model}=${price}`).sort().join("|");
|
|
137
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
|
+
}
|
|
138
207
|
function Section({ title, children }) {
|
|
139
208
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
|
|
140
209
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: caption, children: title }),
|
|
@@ -152,6 +221,7 @@ function Page() {
|
|
|
152
221
|
const [pullModel, setPullModel] = (0, import_react.useState)("");
|
|
153
222
|
const [pull, setPull] = (0, import_react.useState)(null);
|
|
154
223
|
const seeded = (0, import_react.useRef)(false);
|
|
224
|
+
const models = useScrollThumb();
|
|
155
225
|
const [origin, setOrigin] = (0, import_react.useState)(originOf(CANDIDATE_PORTS[0]));
|
|
156
226
|
const originRef = (0, import_react.useRef)(origin);
|
|
157
227
|
originRef.current = origin;
|
|
@@ -451,53 +521,64 @@ function Page() {
|
|
|
451
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"
|
|
452
522
|
) }),
|
|
453
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") }),
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
459
|
-
"input",
|
|
460
|
-
{
|
|
461
|
-
type: "checkbox",
|
|
462
|
-
checked: on,
|
|
463
|
-
"aria-label": name,
|
|
464
|
-
onChange: () => {
|
|
465
|
-
toggleOffer(name);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
),
|
|
469
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
470
|
-
name,
|
|
471
|
-
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 })
|
|
472
|
-
] }),
|
|
473
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", style: { textAlign: "right" }, children: gb(sizeOf.get(name)) }),
|
|
474
|
-
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: [
|
|
475
529
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
476
|
-
|
|
530
|
+
"input",
|
|
477
531
|
{
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
532
|
+
type: "checkbox",
|
|
533
|
+
checked: on,
|
|
534
|
+
"aria-label": name,
|
|
535
|
+
onChange: () => {
|
|
536
|
+
toggleOffer(name);
|
|
537
|
+
}
|
|
483
538
|
}
|
|
484
539
|
),
|
|
485
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
{
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
+
] }),
|
|
501
582
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, justifyContent: "flex-start", gap: 8, marginTop: 12 }, children: [
|
|
502
583
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
503
584
|
import_dsh_client_ui_primitives.Input,
|