@genkaku/dsh-worker-plugin 0.1.10 → 0.1.12
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 +413 -35
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
});
|
|
31
31
|
module.exports = __toCommonJS(index_exports);
|
|
32
32
|
var import_react = require("react");
|
|
33
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
33
34
|
|
|
34
35
|
// src/client/assets/genkaku-mark.png
|
|
35
36
|
var genkaku_mark_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK4AAACuCAMAAACY0sbcAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAmRQTFRFAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Pmgb1QAAAMx0Uk5TAAECBAk7EwMZFwi7/+NcXergkr/yY2mjvPPwIAZg/vX3X2309tMcBR7v+ihL+f2w0csSEIT4nweZI/tvTdwi7fzijNrMMYp9C04yFathCoJP7i7fH8aDYqaAM+te5Ri+5px5VN7oId135HY5Rn6pyjQMQHqnaq84ZuEdazZs23BzbnF0s3w/z7LnEbU1Uxa3UnvBN7nEG8DXVsjCV0fJsTxDuD66QUTQFNaVUem9jewkjkKQWqxZGpElfywnKimTnXWU8Q2g0s5K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";
|
|
@@ -37,8 +38,59 @@ var genkaku_mark_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK4AAA
|
|
|
37
38
|
// src/client/index.tsx
|
|
38
39
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
39
40
|
var PANEL_ID = "genkaku-worker";
|
|
40
|
-
var
|
|
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
45
|
var inject = ["slots"];
|
|
46
|
+
var ZH = typeof navigator !== "undefined" && /^zh/i.test(navigator.language);
|
|
47
|
+
var t = (en, zh) => ZH ? zh : en;
|
|
48
|
+
var DEFAULT_PRICE = "6.00";
|
|
49
|
+
var microToUsdc = (value) => {
|
|
50
|
+
const n = Number(value);
|
|
51
|
+
return Number.isFinite(n) ? (n / 1e6).toFixed(2) : DEFAULT_PRICE;
|
|
52
|
+
};
|
|
53
|
+
var usdcToMicro = (value) => Math.round(Number(value) * 1e6);
|
|
54
|
+
var gb = (bytes) => bytes === void 0 ? "" : `${(bytes / 1e9).toFixed(1)} GB`;
|
|
55
|
+
var row = { display: "flex", justifyContent: "space-between", gap: 12, padding: "6px 0" };
|
|
56
|
+
var dim = { color: "var(--dsw-alias-label-tertiary)" };
|
|
57
|
+
var caption = {
|
|
58
|
+
...dim,
|
|
59
|
+
fontSize: 11,
|
|
60
|
+
textTransform: "uppercase",
|
|
61
|
+
letterSpacing: "0.08em",
|
|
62
|
+
marginBottom: 8
|
|
63
|
+
};
|
|
64
|
+
var box = {
|
|
65
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
66
|
+
borderRadius: "var(--dsw-radius-xl, 12px)",
|
|
67
|
+
background: "var(--dsw-alias-bg-layer-2, transparent)",
|
|
68
|
+
padding: "12px 16px",
|
|
69
|
+
marginTop: 12
|
|
70
|
+
};
|
|
71
|
+
var dot = (on) => ({
|
|
72
|
+
display: "inline-block",
|
|
73
|
+
width: 8,
|
|
74
|
+
height: 8,
|
|
75
|
+
borderRadius: 8,
|
|
76
|
+
marginRight: 8,
|
|
77
|
+
background: on ? "var(--dsw-alias-state-success-primary, #34a853)" : "var(--dsw-alias-label-tertiary)"
|
|
78
|
+
});
|
|
79
|
+
var PANEL_CSS = `
|
|
80
|
+
.gk-row {
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-columns: 20px minmax(0, 1fr) 68px 104px auto;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: 10px;
|
|
85
|
+
padding: 7px 0;
|
|
86
|
+
border-top: 0.5px solid var(--dsw-alias-border-l1);
|
|
87
|
+
}
|
|
88
|
+
.gk-row:first-of-type { border-top: none; }
|
|
89
|
+
.gk-price { width: 88px; }
|
|
90
|
+
.gk-price input { text-align: right; }
|
|
91
|
+
.gk-pull { width: 260px; max-width: 100%; }
|
|
92
|
+
.gk-muted { color: var(--dsw-alias-label-tertiary); font-size: 12px; }
|
|
93
|
+
`;
|
|
42
94
|
function Icon({ size = 16 }) {
|
|
43
95
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", width: size, height: size }, "aria-hidden": "true", children: [
|
|
44
96
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -82,72 +134,398 @@ function Icon({ size = 16 }) {
|
|
|
82
134
|
` })
|
|
83
135
|
] });
|
|
84
136
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
137
|
+
function seedDraft(status) {
|
|
138
|
+
const draft = {};
|
|
139
|
+
for (const entry of status.offers ?? []) {
|
|
140
|
+
const model = entry.offer?.model;
|
|
141
|
+
if (typeof model === "string" && model !== "") draft[model] = microToUsdc(entry.offer?.pricePerHour);
|
|
142
|
+
}
|
|
143
|
+
return draft;
|
|
144
|
+
}
|
|
145
|
+
function draftSignature(draft) {
|
|
146
|
+
return Object.entries(draft).map(([model, price]) => `${model}=${price}`).sort().join("|");
|
|
147
|
+
}
|
|
148
|
+
function Section({ title, children }) {
|
|
149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
|
|
150
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: caption, children: title }),
|
|
151
|
+
children
|
|
152
|
+
] });
|
|
153
|
+
}
|
|
88
154
|
function Page() {
|
|
89
155
|
const [status, setStatus] = (0, import_react.useState)(null);
|
|
156
|
+
const [ollama, setOllama] = (0, import_react.useState)(null);
|
|
90
157
|
const [error, setError] = (0, import_react.useState)(null);
|
|
91
|
-
const
|
|
158
|
+
const [draft, setDraft] = (0, import_react.useState)(null);
|
|
159
|
+
const [notice, setNotice] = (0, import_react.useState)(null);
|
|
160
|
+
const [busy, setBusy] = (0, import_react.useState)(null);
|
|
161
|
+
const [saving, setSaving] = (0, import_react.useState)(false);
|
|
162
|
+
const [pullModel, setPullModel] = (0, import_react.useState)("");
|
|
163
|
+
const [pull, setPull] = (0, import_react.useState)(null);
|
|
164
|
+
const seeded = (0, import_react.useRef)(false);
|
|
165
|
+
const loadStatus = (0, import_react.useCallback)(async () => {
|
|
92
166
|
try {
|
|
93
|
-
const res = await fetch(STATUS_URL);
|
|
167
|
+
const res = await fetch(STATUS_URL, { cache: "no-store" });
|
|
94
168
|
if (!res.ok) throw new Error(`status ${res.status}`);
|
|
95
|
-
|
|
169
|
+
const next = await res.json();
|
|
170
|
+
setStatus(next);
|
|
96
171
|
setError(null);
|
|
172
|
+
if (!seeded.current) {
|
|
173
|
+
seeded.current = true;
|
|
174
|
+
setDraft(seedDraft(next));
|
|
175
|
+
}
|
|
97
176
|
} catch (e) {
|
|
98
177
|
setError(e instanceof Error ? e.message : String(e));
|
|
99
178
|
}
|
|
100
179
|
}, []);
|
|
180
|
+
const loadOllama = (0, import_react.useCallback)(async () => {
|
|
181
|
+
try {
|
|
182
|
+
const res = await fetch(OLLAMA_URL, { cache: "no-store" });
|
|
183
|
+
if (!res.ok) throw new Error(`ollama ${res.status}`);
|
|
184
|
+
setOllama(await res.json());
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
}, []);
|
|
101
188
|
(0, import_react.useEffect)(() => {
|
|
102
|
-
void
|
|
103
|
-
|
|
104
|
-
|
|
189
|
+
void loadStatus();
|
|
190
|
+
void loadOllama();
|
|
191
|
+
const a = setInterval(() => {
|
|
192
|
+
void loadStatus();
|
|
105
193
|
}, 5e3);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
194
|
+
const b = setInterval(() => {
|
|
195
|
+
void loadOllama();
|
|
196
|
+
}, 15e3);
|
|
197
|
+
return () => {
|
|
198
|
+
clearInterval(a);
|
|
199
|
+
clearInterval(b);
|
|
200
|
+
};
|
|
201
|
+
}, [loadStatus, loadOllama]);
|
|
202
|
+
const post = (0, import_react.useCallback)(async (path, body) => {
|
|
203
|
+
const res = await fetch(`${ORIGIN}${path}`, {
|
|
204
|
+
method: "POST",
|
|
205
|
+
headers: { "content-type": "application/json" },
|
|
206
|
+
body: JSON.stringify(body)
|
|
207
|
+
});
|
|
208
|
+
const doc = await res.json().catch(() => null);
|
|
209
|
+
if (!res.ok) throw new Error(doc?.error?.message ?? `HTTP ${res.status}`);
|
|
210
|
+
return doc;
|
|
211
|
+
}, []);
|
|
212
|
+
const startOllama = async () => {
|
|
213
|
+
setBusy("ollama");
|
|
214
|
+
setNotice(null);
|
|
215
|
+
try {
|
|
216
|
+
const next = await post("/genkaku/ollama", {});
|
|
217
|
+
setOllama(next);
|
|
218
|
+
setNotice(next.running === true ? t("Ollama is running.", "Ollama \u5DF2\u555F\u52D5\u3002") : next.error ?? t("Ollama did not start.", "Ollama \u672A\u80FD\u555F\u52D5\u3002"));
|
|
219
|
+
} catch (e) {
|
|
220
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
221
|
+
} finally {
|
|
222
|
+
setBusy(null);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
const pullNow = async () => {
|
|
226
|
+
const model = pullModel.trim();
|
|
227
|
+
if (model === "") return;
|
|
228
|
+
setBusy("pull");
|
|
229
|
+
setNotice(null);
|
|
230
|
+
setPull({ status: t("starting", "\u958B\u59CB\u4E0B\u8F09") });
|
|
231
|
+
try {
|
|
232
|
+
const res = await fetch(`${ORIGIN}/genkaku/ollama/pull`, {
|
|
233
|
+
method: "POST",
|
|
234
|
+
headers: { "content-type": "application/json" },
|
|
235
|
+
body: JSON.stringify({ model })
|
|
236
|
+
});
|
|
237
|
+
if (!res.ok || res.body == null) {
|
|
238
|
+
const doc = await res.json().catch(() => null);
|
|
239
|
+
throw new Error(doc?.error?.message ?? `HTTP ${res.status}`);
|
|
240
|
+
}
|
|
241
|
+
const reader = res.body.getReader();
|
|
242
|
+
const decoder = new TextDecoder();
|
|
243
|
+
let buffer = "";
|
|
244
|
+
for (; ; ) {
|
|
245
|
+
const { value, done } = await reader.read();
|
|
246
|
+
if (done) break;
|
|
247
|
+
buffer += decoder.decode(value, { stream: true });
|
|
248
|
+
const lines = buffer.split("\n");
|
|
249
|
+
buffer = lines.pop() ?? "";
|
|
250
|
+
for (const line of lines) {
|
|
251
|
+
if (line.trim() === "") continue;
|
|
252
|
+
const frame = JSON.parse(line);
|
|
253
|
+
if (frame.error?.message !== void 0) throw new Error(frame.error.message);
|
|
254
|
+
setPull({
|
|
255
|
+
status: frame.status ?? "",
|
|
256
|
+
...frame.percent === void 0 ? {} : { percent: frame.percent }
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
setNotice(t(`Downloaded ${model}.`, `\u5DF2\u4E0B\u8F09 ${model}\u3002`));
|
|
261
|
+
setPullModel("");
|
|
262
|
+
await loadOllama();
|
|
263
|
+
} catch (e) {
|
|
264
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
265
|
+
} finally {
|
|
266
|
+
setBusy(null);
|
|
267
|
+
setPull(null);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
const removeModel = async (model) => {
|
|
271
|
+
if (!window.confirm(t(`Delete ${model} from this machine?`, `\u8981\u5F9E\u672C\u6A5F\u522A\u9664 ${model}\uFF1F`))) return;
|
|
272
|
+
setBusy(`remove:${model}`);
|
|
273
|
+
try {
|
|
274
|
+
await post("/genkaku/ollama/delete", { model });
|
|
275
|
+
await loadOllama();
|
|
276
|
+
await loadStatus();
|
|
277
|
+
} catch (e) {
|
|
278
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
279
|
+
} finally {
|
|
280
|
+
setBusy(null);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const toggleOffer = (model) => {
|
|
284
|
+
setDraft((prev) => {
|
|
285
|
+
const next = { ...prev ?? {} };
|
|
286
|
+
if (model in next) delete next[model];
|
|
287
|
+
else next[model] = DEFAULT_PRICE;
|
|
288
|
+
return next;
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
const save = async () => {
|
|
292
|
+
if (draft == null) return;
|
|
293
|
+
setSaving(true);
|
|
294
|
+
setNotice(null);
|
|
295
|
+
try {
|
|
296
|
+
const known = /* @__PURE__ */ new Map();
|
|
297
|
+
for (const entry of status?.offers ?? []) {
|
|
298
|
+
if (typeof entry.offer?.model === "string") known.set(entry.offer.model, entry.offer);
|
|
299
|
+
}
|
|
300
|
+
const catalog = Object.entries(draft).map(([model, price]) => {
|
|
301
|
+
const n = Number(price);
|
|
302
|
+
if (!Number.isFinite(n) || n < 0) throw new Error(t(`Invalid price for ${model}`, `${model} \u7684\u50F9\u683C\u7121\u6548`));
|
|
303
|
+
const facts = known.get(model);
|
|
304
|
+
return {
|
|
305
|
+
model,
|
|
306
|
+
pricePerHour: usdcToMicro(price),
|
|
307
|
+
...facts?.capabilities === void 0 ? {} : { capabilities: facts.capabilities },
|
|
308
|
+
...facts?.parameterSize === void 0 ? {} : { parameterSize: facts.parameterSize },
|
|
309
|
+
...facts?.tier === void 0 ? {} : { tier: facts.tier }
|
|
310
|
+
};
|
|
311
|
+
});
|
|
312
|
+
const snapshot = await post("/genkaku/catalog", { catalog });
|
|
313
|
+
setStatus(snapshot);
|
|
314
|
+
setDraft(seedDraft(snapshot));
|
|
315
|
+
setNotice(t("Saved \u2014 your catalog is live.", "\u5DF2\u5132\u5B58\uFF0C\u76EE\u9304\u5DF2\u751F\u6548\u3002"));
|
|
316
|
+
} catch (e) {
|
|
317
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
318
|
+
} finally {
|
|
319
|
+
setSaving(false);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const setPublish = async (next) => {
|
|
323
|
+
setBusy("publish");
|
|
324
|
+
setNotice(null);
|
|
325
|
+
try {
|
|
326
|
+
await post("/genkaku/publish", { publish: next });
|
|
327
|
+
setNotice(next ? t("Publishing enabled \u2014 restarting the worker.", "\u5DF2\u958B\u555F\u767C\u4F48\uFF0Cworker \u6B63\u5728\u91CD\u555F\u3002") : t("Publishing disabled \u2014 restarting the worker.", "\u5DF2\u95DC\u9589\u767C\u4F48\uFF0Cworker \u6B63\u5728\u91CD\u555F\u3002"));
|
|
328
|
+
setTimeout(() => {
|
|
329
|
+
void loadStatus();
|
|
330
|
+
}, 3e3);
|
|
331
|
+
} catch (e) {
|
|
332
|
+
setNotice(e instanceof Error ? e.message : String(e));
|
|
333
|
+
} finally {
|
|
334
|
+
setBusy(null);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
if (error != null && status == null) {
|
|
109
338
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16 }, children: [
|
|
110
339
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0 }, children: "GenKaKu worker" }),
|
|
111
340
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { ...dim, marginTop: 8 }, children: [
|
|
112
341
|
"Worker status unreachable: ",
|
|
113
342
|
error
|
|
114
343
|
] }),
|
|
115
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { ...dim, fontSize: 12 }, children: "The plugin starts its status server on 127.0.0.1:47821." })
|
|
344
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { ...dim, fontSize: 12 }, children: "The plugin starts its status server on 127.0.0.1:47821. If another dsh profile is already using that port, this one cannot bind it." })
|
|
116
345
|
] });
|
|
117
346
|
}
|
|
118
347
|
if (status == null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: 16, ...dim }, children: "Loading worker status\u2026" });
|
|
119
|
-
const
|
|
120
|
-
|
|
348
|
+
const installed = ollama?.models ?? [];
|
|
349
|
+
const offered = draft ?? {};
|
|
350
|
+
const tierOf = /* @__PURE__ */ new Map();
|
|
351
|
+
for (const entry of status.offers ?? []) {
|
|
352
|
+
const model = entry.offer?.model;
|
|
353
|
+
const tier = entry.offer?.tier;
|
|
354
|
+
if (typeof model === "string" && typeof tier === "string") tierOf.set(model, tier);
|
|
355
|
+
}
|
|
356
|
+
const names = Array.from(/* @__PURE__ */ new Set([...Object.keys(offered), ...installed.map((m) => m.name)]));
|
|
357
|
+
const sizeOf = new Map(installed.map((m) => [m.name, m.sizeBytes]));
|
|
358
|
+
names.sort((a, b) => {
|
|
359
|
+
const ao = a in offered ? 0 : 1;
|
|
360
|
+
const bo = b in offered ? 0 : 1;
|
|
361
|
+
return ao === bo ? a.localeCompare(b) : ao - bo;
|
|
362
|
+
});
|
|
363
|
+
const dirty = draft !== null && draftSignature(offered) !== draftSignature(seedDraft(status));
|
|
364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16, maxWidth: 760 }, children: [
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: PANEL_CSS }),
|
|
121
366
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { margin: 0 }, children: "GenKaKu worker" }),
|
|
122
367
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, marginTop: 4 }, children: status.role ?? "unknown role" }),
|
|
123
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
368
|
+
notice != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...box, borderColor: "var(--dsw-alias-border-l3)" }, children: notice }),
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { title: "Ollama", children: ollama == null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: dim, children: t("Checking the local Ollama service\u2026", "\u6B63\u5728\u6AA2\u67E5\u672C\u6A5F Ollama \u670D\u52D9\u2026") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
124
370
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
125
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
372
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dot(ollama.running === true) }),
|
|
373
|
+
ollama.running === true ? t("Running", "\u57F7\u884C\u4E2D") : ollama.installed === true ? t("Installed, not running", "\u5DF2\u5B89\u88DD\uFF0C\u672A\u57F7\u884C") : t("Not installed", "\u672A\u5B89\u88DD"),
|
|
374
|
+
ollama.version !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: dim, children: [
|
|
375
|
+
" \xB7 v",
|
|
376
|
+
ollama.version
|
|
377
|
+
] }),
|
|
378
|
+
ollama.running === true && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: dim, children: [
|
|
379
|
+
" \xB7 ",
|
|
380
|
+
installed.length,
|
|
381
|
+
" ",
|
|
382
|
+
t("models", "\u500B\u6A21\u578B")
|
|
383
|
+
] })
|
|
384
|
+
] }),
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: ollama.host ?? "127.0.0.1:11434" }) })
|
|
386
|
+
] }),
|
|
387
|
+
ollama.running !== true && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...row, justifyContent: "flex-start", marginTop: 4 }, children: ollama.installed === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", size: "sm", disabled: busy === "ollama", onClick: () => {
|
|
388
|
+
void startOllama();
|
|
389
|
+
}, children: busy === "ollama" ? t("Starting\u2026", "\u555F\u52D5\u4E2D\u2026") : t("Start Ollama", "\u555F\u52D5 Ollama") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: ollama.downloadUrl ?? "https://ollama.com/download", target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", size: "sm", children: t("Download Ollama", "\u4E0B\u8F09 Ollama") }) }) }),
|
|
390
|
+
ollama.running !== true && ollama.error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginTop: 6 }, children: ollama.error })
|
|
391
|
+
] }) }),
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Section, { title: t("Directory", "\u93C8\u4E0A\u76EE\u9304"), children: [
|
|
393
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, alignItems: "center" }, children: [
|
|
394
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("Publish this worker on-chain", "\u5C07\u6B64 worker \u767C\u4F48\u5230\u93C8\u4E0A\u76EE\u9304") }),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
396
|
+
import_dsh_client_ui_primitives.Switch,
|
|
397
|
+
{
|
|
398
|
+
checked: status.publishAddress === true,
|
|
399
|
+
disabled: busy === "publish",
|
|
400
|
+
label: t("Publish this worker on-chain", "\u5C07\u6B64 worker \u767C\u4F48\u5230\u93C8\u4E0A\u76EE\u9304"),
|
|
401
|
+
onChange: (next) => {
|
|
402
|
+
void setPublish(next);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
] }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginTop: 2 }, children: status.reachable !== true ? t(
|
|
408
|
+
"This machine has no public address, so listing it would create an entry nobody can dial. Peers on the same network can still connect.",
|
|
409
|
+
"\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"
|
|
410
|
+
) : status.publishAddress === true ? t(
|
|
411
|
+
"Listed. Your public IP is written to the chain and stays readable forever, even after you turn this off.",
|
|
412
|
+
"\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"
|
|
413
|
+
) : t(
|
|
414
|
+
"Not listed. A public address is available, so turning this on makes you discoverable.",
|
|
415
|
+
"\u672A\u5217\u51FA\u3002\u9019\u53F0\u6A5F\u5668\u6709\u516C\u7DB2\u4F4D\u5740\uFF0C\u958B\u555F\u5F8C\u5176\u4ED6\u4F7F\u7528\u8005\u624D\u627E\u5F97\u5230\u4F60\u3002"
|
|
416
|
+
) })
|
|
417
|
+
] }),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Section, { title: t("Models offered", "\u4E0A\u67B6\u6A21\u578B"), children: [
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, marginBottom: 8 }, children: t(
|
|
420
|
+
"Unticked models stay installed but are not advertised. Price is USDC per hour; 0 means free.",
|
|
421
|
+
"\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"
|
|
422
|
+
) }),
|
|
423
|
+
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") }),
|
|
424
|
+
names.map((name) => {
|
|
425
|
+
const on = name in offered;
|
|
426
|
+
const tier = tierOf.get(name);
|
|
427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "gk-row", children: [
|
|
428
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
429
|
+
"input",
|
|
430
|
+
{
|
|
431
|
+
type: "checkbox",
|
|
432
|
+
checked: on,
|
|
433
|
+
"aria-label": name,
|
|
434
|
+
onChange: () => {
|
|
435
|
+
toggleOffer(name);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
440
|
+
name,
|
|
441
|
+
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 })
|
|
442
|
+
] }),
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", style: { textAlign: "right" }, children: gb(sizeOf.get(name)) }),
|
|
444
|
+
on ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
446
|
+
import_dsh_client_ui_primitives.Input,
|
|
447
|
+
{
|
|
448
|
+
className: "gk-price",
|
|
449
|
+
value: offered[name] ?? "",
|
|
450
|
+
inputMode: "decimal",
|
|
451
|
+
"aria-label": t(`Price per hour for ${name}`, `${name} \u6BCF\u5C0F\u6642\u50F9\u683C`),
|
|
452
|
+
onChange: (e) => setDraft({ ...draft ?? {}, [name]: e.target.value })
|
|
453
|
+
}
|
|
454
|
+
),
|
|
455
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gk-muted", children: "/h" })
|
|
456
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
458
|
+
import_dsh_client_ui_primitives.Button,
|
|
459
|
+
{
|
|
460
|
+
variant: "ghost",
|
|
461
|
+
size: "sm",
|
|
462
|
+
disabled: busy === `remove:${name}`,
|
|
463
|
+
onClick: () => {
|
|
464
|
+
void removeModel(name);
|
|
465
|
+
},
|
|
466
|
+
children: t("delete", "\u522A\u9664")
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
] }, name);
|
|
470
|
+
}),
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, justifyContent: "flex-start", gap: 8, marginTop: 12 }, children: [
|
|
472
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
473
|
+
import_dsh_client_ui_primitives.Input,
|
|
474
|
+
{
|
|
475
|
+
className: "gk-pull",
|
|
476
|
+
value: pullModel,
|
|
477
|
+
placeholder: t("model to download, e.g. llama3.2:3b", "\u8981\u4E0B\u8F09\u7684\u6A21\u578B\uFF0C\u4F8B\u5982 llama3.2:3b"),
|
|
478
|
+
"aria-label": t("Model to download", "\u8981\u4E0B\u8F09\u7684\u6A21\u578B"),
|
|
479
|
+
onChange: (e) => setPullModel(e.target.value)
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
483
|
+
import_dsh_client_ui_primitives.Button,
|
|
484
|
+
{
|
|
485
|
+
variant: "outline",
|
|
486
|
+
size: "sm",
|
|
487
|
+
disabled: busy === "pull" || pullModel.trim() === "",
|
|
488
|
+
onClick: () => {
|
|
489
|
+
void pullNow();
|
|
490
|
+
},
|
|
491
|
+
children: busy === "pull" ? t("Downloading\u2026", "\u4E0B\u8F09\u4E2D\u2026") : t("Download", "\u4E0B\u8F09")
|
|
492
|
+
}
|
|
493
|
+
),
|
|
494
|
+
pull != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "gk-muted", children: [
|
|
495
|
+
pull.status,
|
|
496
|
+
pull.percent === void 0 ? "" : ` ${Math.round(pull.percent)}%`
|
|
497
|
+
] })
|
|
498
|
+
] }),
|
|
499
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...row, marginTop: 12, alignItems: "center" }, children: [
|
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "gk-muted", children: [
|
|
501
|
+
Object.keys(offered).length,
|
|
502
|
+
" ",
|
|
503
|
+
t("offered", "\u500B\u4E0A\u67B6"),
|
|
504
|
+
dirty ? ` \xB7 ${t("unsaved changes", "\u6709\u672A\u5132\u5B58\u7684\u8B8A\u66F4")}` : ""
|
|
505
|
+
] }),
|
|
506
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { variant: "primary", size: "sm", disabled: saving || !dirty, onClick: () => {
|
|
507
|
+
void save();
|
|
508
|
+
}, children: saving ? t("Saving\u2026", "\u5132\u5B58\u4E2D\u2026") : t("Save catalog", "\u5132\u5B58\u76EE\u9304") })
|
|
509
|
+
] })
|
|
510
|
+
] }),
|
|
511
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Section, { title: "Worker", children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Peer", "Peer") }),
|
|
126
514
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: status.peerId ?? "\u2014" })
|
|
127
515
|
] }),
|
|
128
516
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
129
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "
|
|
130
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Wallet", "\u9322\u5305") }),
|
|
518
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: status.wallet ?? "\u2014" })
|
|
131
519
|
] }),
|
|
132
520
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
133
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "
|
|
134
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.
|
|
521
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Active sessions", "\u9032\u884C\u4E2D session") }),
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: status.activeSessions ?? 0 })
|
|
135
523
|
] }),
|
|
136
524
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: row, children: [
|
|
137
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: "Addresses" }),
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: dim, children: t("Addresses", "\u4F4D\u5740\u6578") }),
|
|
138
526
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: (status.peerAddrs ?? []).length })
|
|
139
|
-
] })
|
|
140
|
-
|
|
141
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: box, children: [
|
|
142
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...dim, fontSize: 12, textTransform: "uppercase", letterSpacing: 1 }, children: "Offered models" }),
|
|
143
|
-
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: [
|
|
144
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: offer.model ?? "\u2014" }),
|
|
145
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: dim, children: [
|
|
146
|
-
offer.pricePerHour ?? "?",
|
|
147
|
-
" / hour",
|
|
148
|
-
offer.tier === "chat" ? " \xB7 not for agents" : ""
|
|
149
|
-
] })
|
|
150
|
-
] }, `${offer.model ?? i}`))
|
|
527
|
+
] }),
|
|
528
|
+
/* @__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") }) })
|
|
151
529
|
] })
|
|
152
530
|
] });
|
|
153
531
|
}
|
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.12",
|
|
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.12",
|
|
42
42
|
"@genkaku/protocol": "0.1.10"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|