@blank-utils/llm 0.2.2 → 0.2.6
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/README.md +487 -89
- package/dist/index.js +1245 -65
- package/dist/react/index.js +1267 -66
- package/package.json +6 -3
- package/dist/backends/transformers.d.ts +0 -62
- package/dist/backends/transformers.d.ts.map +0 -1
- package/dist/backends/webllm.d.ts +0 -70
- package/dist/backends/webllm.d.ts.map +0 -1
- package/dist/core.d.ts +0 -71
- package/dist/core.d.ts.map +0 -1
- package/dist/detect.d.ts +0 -21
- package/dist/detect.d.ts.map +0 -1
- package/dist/helpers.d.ts +0 -35
- package/dist/helpers.d.ts.map +0 -1
- package/dist/index.d.ts +0 -27
- package/dist/index.d.ts.map +0 -1
- package/dist/react/index.d.ts +0 -309
- package/dist/react/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -178
- package/dist/types.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -57,10 +57,10 @@ function getAugmentedNamespace(n) {
|
|
|
57
57
|
return n;
|
|
58
58
|
var f = n.default;
|
|
59
59
|
if (typeof f == "function") {
|
|
60
|
-
var a = function
|
|
60
|
+
var a = function a2() {
|
|
61
61
|
var isInstance = false;
|
|
62
62
|
try {
|
|
63
|
-
isInstance = this instanceof
|
|
63
|
+
isInstance = this instanceof a2;
|
|
64
64
|
} catch {}
|
|
65
65
|
if (isInstance) {
|
|
66
66
|
return Reflect.construct(f, arguments, this.constructor);
|
|
@@ -56591,7 +56591,7 @@ async function logCapabilities() {
|
|
|
56591
56591
|
console.log(` Recommended device: ${caps.recommendedDevice}`);
|
|
56592
56592
|
return caps;
|
|
56593
56593
|
}
|
|
56594
|
-
// src/
|
|
56594
|
+
// src/models.ts
|
|
56595
56595
|
var DEFAULT_WEBLLM_MODEL = "Phi-3.5-mini-instruct-q4f16_1-MLC";
|
|
56596
56596
|
var WEBLLM_MODELS = {
|
|
56597
56597
|
"llama-3.2-1b": "Llama-3.2-1B-Instruct-q4f16_1-MLC",
|
|
@@ -56623,6 +56623,21 @@ var WEBLLM_MODELS = {
|
|
|
56623
56623
|
"hermes-3-llama-3.2-3b": "Hermes-3-Llama-3.2-3B-q4f16_1-MLC",
|
|
56624
56624
|
"hermes-3-llama-3.1-8b": "Hermes-3-Llama-3.1-8B-q4f16_1-MLC"
|
|
56625
56625
|
};
|
|
56626
|
+
var DEFAULT_TRANSFORMERS_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
|
|
56627
|
+
var TRANSFORMERS_MODELS = {
|
|
56628
|
+
"qwen-2.5-0.5b": "onnx-community/Qwen2.5-0.5B-Instruct",
|
|
56629
|
+
"qwen-2.5-1.5b": "onnx-community/Qwen2.5-1.5B-Instruct",
|
|
56630
|
+
"qwen-2.5-coder-0.5b": "onnx-community/Qwen2.5-Coder-0.5B-Instruct",
|
|
56631
|
+
"qwen-2.5-coder-1.5b": "onnx-community/Qwen2.5-Coder-1.5B-Instruct",
|
|
56632
|
+
"qwen-3-0.6b": "onnx-community/Qwen3-0.6B-ONNX",
|
|
56633
|
+
"smollm2-135m": "HuggingFaceTB/SmolLM2-135M-Instruct",
|
|
56634
|
+
"smollm2-360m": "HuggingFaceTB/SmolLM2-360M-Instruct",
|
|
56635
|
+
"smollm2-1.7b": "HuggingFaceTB/SmolLM2-1.7B-Instruct",
|
|
56636
|
+
"phi-3-mini": "Xenova/Phi-3-mini-4k-instruct",
|
|
56637
|
+
tinyllama: "Xenova/TinyLlama-1.1B-Chat-v1.0"
|
|
56638
|
+
};
|
|
56639
|
+
|
|
56640
|
+
// src/backends/webllm.ts
|
|
56626
56641
|
function resolveModelId(model) {
|
|
56627
56642
|
if (model in WEBLLM_MODELS) {
|
|
56628
56643
|
return WEBLLM_MODELS[model];
|
|
@@ -56710,19 +56725,6 @@ function createWebLLMProvider() {
|
|
|
56710
56725
|
return new WebLLMProvider;
|
|
56711
56726
|
}
|
|
56712
56727
|
// src/backends/transformers.ts
|
|
56713
|
-
var DEFAULT_TRANSFORMERS_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
|
|
56714
|
-
var TRANSFORMERS_MODELS = {
|
|
56715
|
-
"qwen-2.5-0.5b": "onnx-community/Qwen2.5-0.5B-Instruct",
|
|
56716
|
-
"qwen-2.5-1.5b": "onnx-community/Qwen2.5-1.5B-Instruct",
|
|
56717
|
-
"qwen-2.5-coder-0.5b": "onnx-community/Qwen2.5-Coder-0.5B-Instruct",
|
|
56718
|
-
"qwen-2.5-coder-1.5b": "onnx-community/Qwen2.5-Coder-1.5B-Instruct",
|
|
56719
|
-
"qwen-3-0.6b": "onnx-community/Qwen3-0.6B-ONNX",
|
|
56720
|
-
"smollm2-135m": "HuggingFaceTB/SmolLM2-135M-Instruct",
|
|
56721
|
-
"smollm2-360m": "HuggingFaceTB/SmolLM2-360M-Instruct",
|
|
56722
|
-
"smollm2-1.7b": "HuggingFaceTB/SmolLM2-1.7B-Instruct",
|
|
56723
|
-
"phi-3-mini": "Xenova/Phi-3-mini-4k-instruct",
|
|
56724
|
-
tinyllama: "Xenova/TinyLlama-1.1B-Chat-v1.0"
|
|
56725
|
-
};
|
|
56726
56728
|
function detectChatFormat(modelId) {
|
|
56727
56729
|
const lower = modelId.toLowerCase();
|
|
56728
56730
|
if (lower.includes("qwen") || lower.includes("smollm")) {
|
|
@@ -57127,13 +57129,1189 @@ async function isWebGPUSupported() {
|
|
|
57127
57129
|
import {
|
|
57128
57130
|
createContext,
|
|
57129
57131
|
useContext,
|
|
57130
|
-
useState,
|
|
57131
|
-
useCallback,
|
|
57132
|
-
useEffect,
|
|
57133
|
-
useMemo,
|
|
57134
|
-
useRef
|
|
57132
|
+
useState as useState3,
|
|
57133
|
+
useCallback as useCallback2,
|
|
57134
|
+
useEffect as useEffect3,
|
|
57135
|
+
useMemo as useMemo2,
|
|
57136
|
+
useRef as useRef3
|
|
57135
57137
|
} from "react";
|
|
57138
|
+
|
|
57139
|
+
// src/react/components.tsx
|
|
57140
|
+
import { useRef as useRef2, useEffect as useEffect2, useState as useState2, useMemo } from "react";
|
|
57141
|
+
|
|
57142
|
+
// src/react/chat-input.tsx
|
|
57143
|
+
import { useRef, useEffect, useCallback, useState } from "react";
|
|
57136
57144
|
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
57145
|
+
function SendIcon() {
|
|
57146
|
+
return /* @__PURE__ */ jsxDEV("svg", {
|
|
57147
|
+
width: "14",
|
|
57148
|
+
height: "14",
|
|
57149
|
+
viewBox: "0 0 24 24",
|
|
57150
|
+
fill: "none",
|
|
57151
|
+
stroke: "currentColor",
|
|
57152
|
+
strokeWidth: "2",
|
|
57153
|
+
strokeLinecap: "round",
|
|
57154
|
+
strokeLinejoin: "round",
|
|
57155
|
+
children: [
|
|
57156
|
+
/* @__PURE__ */ jsxDEV("line", {
|
|
57157
|
+
x1: "5",
|
|
57158
|
+
y1: "12",
|
|
57159
|
+
x2: "19",
|
|
57160
|
+
y2: "12"
|
|
57161
|
+
}, undefined, false, undefined, this),
|
|
57162
|
+
/* @__PURE__ */ jsxDEV("polyline", {
|
|
57163
|
+
points: "12 5 19 12 12 19"
|
|
57164
|
+
}, undefined, false, undefined, this)
|
|
57165
|
+
]
|
|
57166
|
+
}, undefined, true, undefined, this);
|
|
57167
|
+
}
|
|
57168
|
+
function StopIcon() {
|
|
57169
|
+
return /* @__PURE__ */ jsxDEV("svg", {
|
|
57170
|
+
width: "14",
|
|
57171
|
+
height: "14",
|
|
57172
|
+
viewBox: "0 0 24 24",
|
|
57173
|
+
fill: "currentColor",
|
|
57174
|
+
children: /* @__PURE__ */ jsxDEV("rect", {
|
|
57175
|
+
x: "6",
|
|
57176
|
+
y: "6",
|
|
57177
|
+
width: "12",
|
|
57178
|
+
height: "12"
|
|
57179
|
+
}, undefined, false, undefined, this)
|
|
57180
|
+
}, undefined, false, undefined, this);
|
|
57181
|
+
}
|
|
57182
|
+
function ImageIcon() {
|
|
57183
|
+
return /* @__PURE__ */ jsxDEV("svg", {
|
|
57184
|
+
width: "14",
|
|
57185
|
+
height: "14",
|
|
57186
|
+
viewBox: "0 0 24 24",
|
|
57187
|
+
fill: "none",
|
|
57188
|
+
stroke: "currentColor",
|
|
57189
|
+
strokeWidth: "2",
|
|
57190
|
+
strokeLinecap: "round",
|
|
57191
|
+
strokeLinejoin: "round",
|
|
57192
|
+
children: [
|
|
57193
|
+
/* @__PURE__ */ jsxDEV("rect", {
|
|
57194
|
+
x: "3",
|
|
57195
|
+
y: "3",
|
|
57196
|
+
width: "18",
|
|
57197
|
+
height: "18",
|
|
57198
|
+
rx: "0",
|
|
57199
|
+
ry: "0"
|
|
57200
|
+
}, undefined, false, undefined, this),
|
|
57201
|
+
/* @__PURE__ */ jsxDEV("circle", {
|
|
57202
|
+
cx: "8.5",
|
|
57203
|
+
cy: "8.5",
|
|
57204
|
+
r: "1.5"
|
|
57205
|
+
}, undefined, false, undefined, this),
|
|
57206
|
+
/* @__PURE__ */ jsxDEV("polyline", {
|
|
57207
|
+
points: "21 15 16 10 5 21"
|
|
57208
|
+
}, undefined, false, undefined, this)
|
|
57209
|
+
]
|
|
57210
|
+
}, undefined, true, undefined, this);
|
|
57211
|
+
}
|
|
57212
|
+
function XIcon() {
|
|
57213
|
+
return /* @__PURE__ */ jsxDEV("svg", {
|
|
57214
|
+
width: "10",
|
|
57215
|
+
height: "10",
|
|
57216
|
+
viewBox: "0 0 24 24",
|
|
57217
|
+
fill: "none",
|
|
57218
|
+
stroke: "currentColor",
|
|
57219
|
+
strokeWidth: "3",
|
|
57220
|
+
strokeLinecap: "round",
|
|
57221
|
+
strokeLinejoin: "round",
|
|
57222
|
+
children: [
|
|
57223
|
+
/* @__PURE__ */ jsxDEV("line", {
|
|
57224
|
+
x1: "18",
|
|
57225
|
+
y1: "6",
|
|
57226
|
+
x2: "6",
|
|
57227
|
+
y2: "18"
|
|
57228
|
+
}, undefined, false, undefined, this),
|
|
57229
|
+
/* @__PURE__ */ jsxDEV("line", {
|
|
57230
|
+
x1: "6",
|
|
57231
|
+
y1: "6",
|
|
57232
|
+
x2: "18",
|
|
57233
|
+
y2: "18"
|
|
57234
|
+
}, undefined, false, undefined, this)
|
|
57235
|
+
]
|
|
57236
|
+
}, undefined, true, undefined, this);
|
|
57237
|
+
}
|
|
57238
|
+
var STYLE_ID = "__llm-chat-input-styles";
|
|
57239
|
+
function injectStyles(theme) {
|
|
57240
|
+
if (typeof document === "undefined")
|
|
57241
|
+
return;
|
|
57242
|
+
const existing = document.getElementById(STYLE_ID);
|
|
57243
|
+
if (existing)
|
|
57244
|
+
existing.remove();
|
|
57245
|
+
const d = theme === "dark";
|
|
57246
|
+
const border = d ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.12)";
|
|
57247
|
+
const borderFocus = d ? "rgba(255,255,255,0.35)" : "rgba(0,0,0,0.35)";
|
|
57248
|
+
const bg2 = d ? "#000000" : "#ffffff";
|
|
57249
|
+
const text = d ? "#ffffff" : "#000000";
|
|
57250
|
+
const textMuted = d ? "rgba(255,255,255,0.3)" : "rgba(0,0,0,0.3)";
|
|
57251
|
+
const textSecondary = d ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)";
|
|
57252
|
+
const monoFont = `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace`;
|
|
57253
|
+
const sansFont = `-apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto, Helvetica, Arial, sans-serif`;
|
|
57254
|
+
const css = `
|
|
57255
|
+
.llm-ci {
|
|
57256
|
+
display: flex;
|
|
57257
|
+
flex-direction: column;
|
|
57258
|
+
border: 1px solid ${border};
|
|
57259
|
+
background: ${bg2};
|
|
57260
|
+
padding: 12px;
|
|
57261
|
+
transition: border-color 0.15s;
|
|
57262
|
+
position: relative;
|
|
57263
|
+
}
|
|
57264
|
+
.llm-ci:focus-within {
|
|
57265
|
+
border-color: ${borderFocus};
|
|
57266
|
+
}
|
|
57267
|
+
|
|
57268
|
+
/* Attached Images */
|
|
57269
|
+
.llm-ci-images {
|
|
57270
|
+
display: flex;
|
|
57271
|
+
flex-wrap: wrap;
|
|
57272
|
+
gap: 6px;
|
|
57273
|
+
margin-bottom: 8px;
|
|
57274
|
+
}
|
|
57275
|
+
.llm-ci-image-preview {
|
|
57276
|
+
position: relative;
|
|
57277
|
+
width: 52px;
|
|
57278
|
+
height: 52px;
|
|
57279
|
+
overflow: hidden;
|
|
57280
|
+
border: 1px solid ${border};
|
|
57281
|
+
}
|
|
57282
|
+
.llm-ci-image-preview img {
|
|
57283
|
+
width: 100%;
|
|
57284
|
+
height: 100%;
|
|
57285
|
+
object-fit: cover;
|
|
57286
|
+
}
|
|
57287
|
+
.llm-ci-image-remove {
|
|
57288
|
+
position: absolute;
|
|
57289
|
+
top: 2px;
|
|
57290
|
+
right: 2px;
|
|
57291
|
+
width: 16px;
|
|
57292
|
+
height: 16px;
|
|
57293
|
+
background: ${d ? "rgba(0,0,0,0.7)" : "rgba(255,255,255,0.8)"};
|
|
57294
|
+
color: ${text};
|
|
57295
|
+
border: none;
|
|
57296
|
+
display: flex;
|
|
57297
|
+
align-items: center;
|
|
57298
|
+
justify-content: center;
|
|
57299
|
+
cursor: pointer;
|
|
57300
|
+
opacity: 0;
|
|
57301
|
+
transition: opacity 0.1s;
|
|
57302
|
+
}
|
|
57303
|
+
.llm-ci-image-preview:hover .llm-ci-image-remove {
|
|
57304
|
+
opacity: 1;
|
|
57305
|
+
}
|
|
57306
|
+
|
|
57307
|
+
/* Textarea */
|
|
57308
|
+
.llm-ci textarea {
|
|
57309
|
+
width: 100%;
|
|
57310
|
+
min-height: 24px;
|
|
57311
|
+
max-height: 200px;
|
|
57312
|
+
resize: none;
|
|
57313
|
+
border: none;
|
|
57314
|
+
outline: none;
|
|
57315
|
+
background: transparent;
|
|
57316
|
+
color: ${text};
|
|
57317
|
+
font-size: 14px;
|
|
57318
|
+
line-height: 1.5;
|
|
57319
|
+
padding: 0;
|
|
57320
|
+
margin: 0;
|
|
57321
|
+
font-family: ${sansFont};
|
|
57322
|
+
scrollbar-width: thin;
|
|
57323
|
+
}
|
|
57324
|
+
.llm-ci textarea::placeholder {
|
|
57325
|
+
color: ${textMuted};
|
|
57326
|
+
}
|
|
57327
|
+
|
|
57328
|
+
/* Toolbar */
|
|
57329
|
+
.llm-ci-toolbar {
|
|
57330
|
+
display: flex;
|
|
57331
|
+
align-items: center;
|
|
57332
|
+
justify-content: space-between;
|
|
57333
|
+
margin-top: 8px;
|
|
57334
|
+
min-height: 28px;
|
|
57335
|
+
}
|
|
57336
|
+
.llm-ci-left-actions {
|
|
57337
|
+
display: flex;
|
|
57338
|
+
align-items: center;
|
|
57339
|
+
gap: 2px;
|
|
57340
|
+
}
|
|
57341
|
+
.llm-ci-right-actions {
|
|
57342
|
+
display: flex;
|
|
57343
|
+
align-items: center;
|
|
57344
|
+
gap: 8px;
|
|
57345
|
+
}
|
|
57346
|
+
|
|
57347
|
+
/* Icon Buttons */
|
|
57348
|
+
.llm-ci-btn-icon {
|
|
57349
|
+
display: flex;
|
|
57350
|
+
align-items: center;
|
|
57351
|
+
justify-content: center;
|
|
57352
|
+
width: 28px;
|
|
57353
|
+
height: 28px;
|
|
57354
|
+
border: none;
|
|
57355
|
+
background: transparent;
|
|
57356
|
+
color: ${textSecondary};
|
|
57357
|
+
cursor: pointer;
|
|
57358
|
+
transition: color 0.1s;
|
|
57359
|
+
}
|
|
57360
|
+
.llm-ci-btn-icon:hover {
|
|
57361
|
+
color: ${text};
|
|
57362
|
+
}
|
|
57363
|
+
|
|
57364
|
+
/* Send / Stop — flat, monospace, uppercase */
|
|
57365
|
+
.llm-ci-send {
|
|
57366
|
+
display: flex;
|
|
57367
|
+
align-items: center;
|
|
57368
|
+
justify-content: center;
|
|
57369
|
+
height: 28px;
|
|
57370
|
+
padding: 0 12px;
|
|
57371
|
+
border: 1px solid ${border};
|
|
57372
|
+
font-size: 10px;
|
|
57373
|
+
font-weight: 400;
|
|
57374
|
+
font-family: ${monoFont};
|
|
57375
|
+
text-transform: uppercase;
|
|
57376
|
+
letter-spacing: 0.08em;
|
|
57377
|
+
cursor: pointer;
|
|
57378
|
+
transition: all 0.1s;
|
|
57379
|
+
gap: 6px;
|
|
57380
|
+
background: transparent;
|
|
57381
|
+
color: ${textSecondary};
|
|
57382
|
+
}
|
|
57383
|
+
.llm-ci-send--active {
|
|
57384
|
+
background: ${text};
|
|
57385
|
+
color: ${bg2};
|
|
57386
|
+
border-color: ${text};
|
|
57387
|
+
}
|
|
57388
|
+
.llm-ci-send--active:hover {
|
|
57389
|
+
opacity: 0.8;
|
|
57390
|
+
}
|
|
57391
|
+
.llm-ci-send--disabled {
|
|
57392
|
+
color: ${textMuted};
|
|
57393
|
+
border-color: ${d ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.06)"};
|
|
57394
|
+
cursor: not-allowed;
|
|
57395
|
+
}
|
|
57396
|
+
.llm-ci-send--stop {
|
|
57397
|
+
background: transparent;
|
|
57398
|
+
border-color: ${border};
|
|
57399
|
+
color: ${textSecondary};
|
|
57400
|
+
}
|
|
57401
|
+
.llm-ci-send--stop:hover {
|
|
57402
|
+
border-color: ${borderFocus};
|
|
57403
|
+
color: ${text};
|
|
57404
|
+
}
|
|
57405
|
+
|
|
57406
|
+
/* Model Selector Slot */
|
|
57407
|
+
.llm-ci-model-selector {
|
|
57408
|
+
margin-right: auto;
|
|
57409
|
+
}
|
|
57410
|
+
|
|
57411
|
+
/* Hidden file input */
|
|
57412
|
+
.llm-ci-file-input {
|
|
57413
|
+
display: none;
|
|
57414
|
+
}
|
|
57415
|
+
|
|
57416
|
+
/* Drag Overlay */
|
|
57417
|
+
.llm-ci-drag-overlay {
|
|
57418
|
+
position: absolute;
|
|
57419
|
+
inset: 0;
|
|
57420
|
+
background: ${d ? "rgba(0,0,0,0.9)" : "rgba(255,255,255,0.9)"};
|
|
57421
|
+
display: flex;
|
|
57422
|
+
align-items: center;
|
|
57423
|
+
justify-content: center;
|
|
57424
|
+
z-index: 10;
|
|
57425
|
+
border: 1px dashed ${textSecondary};
|
|
57426
|
+
color: ${textSecondary};
|
|
57427
|
+
font-size: 11px;
|
|
57428
|
+
font-family: ${monoFont};
|
|
57429
|
+
text-transform: uppercase;
|
|
57430
|
+
letter-spacing: 0.08em;
|
|
57431
|
+
}
|
|
57432
|
+
`;
|
|
57433
|
+
const style = document.createElement("style");
|
|
57434
|
+
style.id = STYLE_ID;
|
|
57435
|
+
style.textContent = css;
|
|
57436
|
+
document.head.appendChild(style);
|
|
57437
|
+
}
|
|
57438
|
+
function ChatInput({
|
|
57439
|
+
value,
|
|
57440
|
+
onChange,
|
|
57441
|
+
onSend,
|
|
57442
|
+
onStop,
|
|
57443
|
+
disabled = false,
|
|
57444
|
+
isGenerating = false,
|
|
57445
|
+
placeholder = "Type a message...",
|
|
57446
|
+
maxRows = 8,
|
|
57447
|
+
actions,
|
|
57448
|
+
theme = "dark",
|
|
57449
|
+
className,
|
|
57450
|
+
images = [],
|
|
57451
|
+
onImageAdd,
|
|
57452
|
+
onImageRemove,
|
|
57453
|
+
modelSelector
|
|
57454
|
+
}) {
|
|
57455
|
+
const textareaRef = useRef(null);
|
|
57456
|
+
const fileInputRef = useRef(null);
|
|
57457
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
57458
|
+
useEffect(() => {
|
|
57459
|
+
injectStyles(theme);
|
|
57460
|
+
}, [theme]);
|
|
57461
|
+
useEffect(() => {
|
|
57462
|
+
const textarea = textareaRef.current;
|
|
57463
|
+
if (!textarea)
|
|
57464
|
+
return;
|
|
57465
|
+
textarea.style.height = "auto";
|
|
57466
|
+
const lineHeight = 21;
|
|
57467
|
+
const maxHeight = lineHeight * maxRows + 24;
|
|
57468
|
+
const newHeight = Math.min(textarea.scrollHeight, maxHeight);
|
|
57469
|
+
textarea.style.height = `${newHeight}px`;
|
|
57470
|
+
}, [value, maxRows]);
|
|
57471
|
+
const handleKeyDown = useCallback((e) => {
|
|
57472
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
57473
|
+
e.preventDefault();
|
|
57474
|
+
if (!disabled && (value.trim() || images.length > 0)) {
|
|
57475
|
+
onSend();
|
|
57476
|
+
}
|
|
57477
|
+
}
|
|
57478
|
+
}, [disabled, value, images.length, onSend]);
|
|
57479
|
+
const processFile = useCallback((file) => {
|
|
57480
|
+
if (!file.type.startsWith("image/"))
|
|
57481
|
+
return;
|
|
57482
|
+
const reader = new FileReader;
|
|
57483
|
+
reader.onload = (e) => {
|
|
57484
|
+
if (e.target?.result && typeof e.target.result === "string") {
|
|
57485
|
+
const id2 = Math.random().toString(36).substring(7);
|
|
57486
|
+
onImageAdd?.({
|
|
57487
|
+
id: id2,
|
|
57488
|
+
dataUrl: e.target.result,
|
|
57489
|
+
file,
|
|
57490
|
+
name: file.name
|
|
57491
|
+
});
|
|
57492
|
+
}
|
|
57493
|
+
};
|
|
57494
|
+
reader.readAsDataURL(file);
|
|
57495
|
+
}, [onImageAdd]);
|
|
57496
|
+
const handlePaste = useCallback((e) => {
|
|
57497
|
+
const items = e.clipboardData.items;
|
|
57498
|
+
for (let i = 0;i < items.length; i++) {
|
|
57499
|
+
const item = items[i];
|
|
57500
|
+
if (item && item.type.indexOf("image") !== -1) {
|
|
57501
|
+
const file = item.getAsFile();
|
|
57502
|
+
if (file)
|
|
57503
|
+
processFile(file);
|
|
57504
|
+
}
|
|
57505
|
+
}
|
|
57506
|
+
}, [processFile]);
|
|
57507
|
+
const handleDrop = useCallback((e) => {
|
|
57508
|
+
e.preventDefault();
|
|
57509
|
+
setIsDragging(false);
|
|
57510
|
+
const files = e.dataTransfer.files;
|
|
57511
|
+
for (let i = 0;i < files.length; i++) {
|
|
57512
|
+
const file = files.item(i);
|
|
57513
|
+
if (file)
|
|
57514
|
+
processFile(file);
|
|
57515
|
+
}
|
|
57516
|
+
}, [processFile]);
|
|
57517
|
+
const handleFileSelect = useCallback((e) => {
|
|
57518
|
+
const files = e.target.files;
|
|
57519
|
+
if (!files)
|
|
57520
|
+
return;
|
|
57521
|
+
for (let i = 0;i < files.length; i++) {
|
|
57522
|
+
const file = files.item(i);
|
|
57523
|
+
if (file)
|
|
57524
|
+
processFile(file);
|
|
57525
|
+
}
|
|
57526
|
+
e.target.value = "";
|
|
57527
|
+
}, [processFile]);
|
|
57528
|
+
const hasValue = value.trim().length > 0 || images.length > 0;
|
|
57529
|
+
const canSend = hasValue && !disabled && !isGenerating;
|
|
57530
|
+
let sendClass = "llm-ci-send";
|
|
57531
|
+
if (isGenerating) {
|
|
57532
|
+
sendClass += " llm-ci-send--stop";
|
|
57533
|
+
} else if (canSend) {
|
|
57534
|
+
sendClass += " llm-ci-send--active";
|
|
57535
|
+
} else {
|
|
57536
|
+
sendClass += " llm-ci-send--disabled";
|
|
57537
|
+
}
|
|
57538
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
57539
|
+
className: `llm-ci${className ? ` ${className}` : ""}`,
|
|
57540
|
+
onDragOver: (e) => {
|
|
57541
|
+
e.preventDefault();
|
|
57542
|
+
setIsDragging(true);
|
|
57543
|
+
},
|
|
57544
|
+
onDragLeave: () => setIsDragging(false),
|
|
57545
|
+
onDrop: handleDrop,
|
|
57546
|
+
children: [
|
|
57547
|
+
isDragging && /* @__PURE__ */ jsxDEV("div", {
|
|
57548
|
+
className: "llm-ci-drag-overlay",
|
|
57549
|
+
children: "[Drop image to attach]"
|
|
57550
|
+
}, undefined, false, undefined, this),
|
|
57551
|
+
/* @__PURE__ */ jsxDEV("input", {
|
|
57552
|
+
ref: fileInputRef,
|
|
57553
|
+
type: "file",
|
|
57554
|
+
accept: "image/*",
|
|
57555
|
+
multiple: true,
|
|
57556
|
+
className: "llm-ci-file-input",
|
|
57557
|
+
onChange: handleFileSelect
|
|
57558
|
+
}, undefined, false, undefined, this),
|
|
57559
|
+
images.length > 0 && /* @__PURE__ */ jsxDEV("div", {
|
|
57560
|
+
className: "llm-ci-images",
|
|
57561
|
+
children: images.map((img) => /* @__PURE__ */ jsxDEV("div", {
|
|
57562
|
+
className: "llm-ci-image-preview",
|
|
57563
|
+
children: [
|
|
57564
|
+
/* @__PURE__ */ jsxDEV("img", {
|
|
57565
|
+
src: img.dataUrl,
|
|
57566
|
+
alt: "attachment"
|
|
57567
|
+
}, undefined, false, undefined, this),
|
|
57568
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
57569
|
+
type: "button",
|
|
57570
|
+
className: "llm-ci-image-remove",
|
|
57571
|
+
onClick: () => onImageRemove?.(img.id),
|
|
57572
|
+
children: /* @__PURE__ */ jsxDEV(XIcon, {}, undefined, false, undefined, this)
|
|
57573
|
+
}, undefined, false, undefined, this)
|
|
57574
|
+
]
|
|
57575
|
+
}, img.id, true, undefined, this))
|
|
57576
|
+
}, undefined, false, undefined, this),
|
|
57577
|
+
/* @__PURE__ */ jsxDEV("textarea", {
|
|
57578
|
+
ref: textareaRef,
|
|
57579
|
+
value,
|
|
57580
|
+
onChange: (e) => onChange(e.target.value),
|
|
57581
|
+
onKeyDown: handleKeyDown,
|
|
57582
|
+
onPaste: handlePaste,
|
|
57583
|
+
placeholder,
|
|
57584
|
+
disabled: disabled && !isGenerating,
|
|
57585
|
+
rows: 1
|
|
57586
|
+
}, undefined, false, undefined, this),
|
|
57587
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
57588
|
+
className: "llm-ci-toolbar",
|
|
57589
|
+
children: [
|
|
57590
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
57591
|
+
className: "llm-ci-left-actions",
|
|
57592
|
+
children: [
|
|
57593
|
+
modelSelector && /* @__PURE__ */ jsxDEV("div", {
|
|
57594
|
+
className: "llm-ci-model-selector",
|
|
57595
|
+
children: modelSelector
|
|
57596
|
+
}, undefined, false, undefined, this),
|
|
57597
|
+
/* @__PURE__ */ jsxDEV("button", {
|
|
57598
|
+
type: "button",
|
|
57599
|
+
className: "llm-ci-btn-icon",
|
|
57600
|
+
onClick: () => fileInputRef.current?.click(),
|
|
57601
|
+
title: "Attach image (or Ctrl+V to paste)",
|
|
57602
|
+
children: /* @__PURE__ */ jsxDEV(ImageIcon, {}, undefined, false, undefined, this)
|
|
57603
|
+
}, undefined, false, undefined, this),
|
|
57604
|
+
actions
|
|
57605
|
+
]
|
|
57606
|
+
}, undefined, true, undefined, this),
|
|
57607
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
57608
|
+
className: "llm-ci-right-actions",
|
|
57609
|
+
children: /* @__PURE__ */ jsxDEV("button", {
|
|
57610
|
+
type: "button",
|
|
57611
|
+
className: sendClass,
|
|
57612
|
+
onClick: isGenerating ? onStop : onSend,
|
|
57613
|
+
disabled: !isGenerating && !canSend,
|
|
57614
|
+
"aria-label": isGenerating ? "Stop generation" : "Send message",
|
|
57615
|
+
children: isGenerating ? /* @__PURE__ */ jsxDEV(Fragment, {
|
|
57616
|
+
children: [
|
|
57617
|
+
/* @__PURE__ */ jsxDEV(StopIcon, {}, undefined, false, undefined, this),
|
|
57618
|
+
" Stop"
|
|
57619
|
+
]
|
|
57620
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV(Fragment, {
|
|
57621
|
+
children: [
|
|
57622
|
+
"Send ",
|
|
57623
|
+
/* @__PURE__ */ jsxDEV(SendIcon, {}, undefined, false, undefined, this)
|
|
57624
|
+
]
|
|
57625
|
+
}, undefined, true, undefined, this)
|
|
57626
|
+
}, undefined, false, undefined, this)
|
|
57627
|
+
}, undefined, false, undefined, this)
|
|
57628
|
+
]
|
|
57629
|
+
}, undefined, true, undefined, this)
|
|
57630
|
+
]
|
|
57631
|
+
}, undefined, true, undefined, this);
|
|
57632
|
+
}
|
|
57633
|
+
|
|
57634
|
+
// src/react/components.tsx
|
|
57635
|
+
import { Streamdown } from "streamdown";
|
|
57636
|
+
import { code } from "@streamdown/code";
|
|
57637
|
+
import { mermaid } from "@streamdown/mermaid";
|
|
57638
|
+
import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime";
|
|
57639
|
+
var DEFAULT_SYSTEM_PROMPT = `You are a helpful AI assistant.
|
|
57640
|
+
- You can use full Markdown (bold, italic, headers, lists).
|
|
57641
|
+
- You can use Code Blocks with language syntax highlighting.
|
|
57642
|
+
- You can use Mermaid diagrams (\`\`\`mermaid ... \`\`\`).
|
|
57643
|
+
- You can use LaTeX math ($$ ... $$).`;
|
|
57644
|
+
var ALL_MODELS = { ...WEBLLM_MODELS, ...TRANSFORMERS_MODELS };
|
|
57645
|
+
function RetryIcon() {
|
|
57646
|
+
return /* @__PURE__ */ jsxDEV2("svg", {
|
|
57647
|
+
width: "14",
|
|
57648
|
+
height: "14",
|
|
57649
|
+
viewBox: "0 0 24 24",
|
|
57650
|
+
fill: "none",
|
|
57651
|
+
stroke: "currentColor",
|
|
57652
|
+
strokeWidth: "2",
|
|
57653
|
+
strokeLinecap: "round",
|
|
57654
|
+
strokeLinejoin: "round",
|
|
57655
|
+
children: [
|
|
57656
|
+
/* @__PURE__ */ jsxDEV2("polyline", {
|
|
57657
|
+
points: "23 4 23 10 17 10"
|
|
57658
|
+
}, undefined, false, undefined, this),
|
|
57659
|
+
/* @__PURE__ */ jsxDEV2("path", {
|
|
57660
|
+
d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10"
|
|
57661
|
+
}, undefined, false, undefined, this)
|
|
57662
|
+
]
|
|
57663
|
+
}, undefined, true, undefined, this);
|
|
57664
|
+
}
|
|
57665
|
+
function ChevronDownIcon() {
|
|
57666
|
+
return /* @__PURE__ */ jsxDEV2("svg", {
|
|
57667
|
+
width: "12",
|
|
57668
|
+
height: "12",
|
|
57669
|
+
viewBox: "0 0 24 24",
|
|
57670
|
+
fill: "none",
|
|
57671
|
+
stroke: "currentColor",
|
|
57672
|
+
strokeWidth: "2",
|
|
57673
|
+
strokeLinecap: "round",
|
|
57674
|
+
strokeLinejoin: "round",
|
|
57675
|
+
children: /* @__PURE__ */ jsxDEV2("polyline", {
|
|
57676
|
+
points: "6 9 12 15 18 9"
|
|
57677
|
+
}, undefined, false, undefined, this)
|
|
57678
|
+
}, undefined, false, undefined, this);
|
|
57679
|
+
}
|
|
57680
|
+
var STYLE_ID2 = "__llm-chat-styles";
|
|
57681
|
+
function injectChatStyles(theme) {
|
|
57682
|
+
if (typeof document === "undefined")
|
|
57683
|
+
return;
|
|
57684
|
+
const existing = document.getElementById(STYLE_ID2);
|
|
57685
|
+
if (existing)
|
|
57686
|
+
existing.remove();
|
|
57687
|
+
const d = theme === "dark";
|
|
57688
|
+
const bg2 = d ? "#000000" : "#ffffff";
|
|
57689
|
+
const border = d ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.12)";
|
|
57690
|
+
const borderSubtle = d ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.06)";
|
|
57691
|
+
const text = d ? "#ffffff" : "#000000";
|
|
57692
|
+
const textSecondary = d ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.5)";
|
|
57693
|
+
const textTertiary = d ? "rgba(255,255,255,0.3)" : "rgba(0,0,0,0.3)";
|
|
57694
|
+
const surfaceSubtle = d ? "rgba(255,255,255,0.04)" : "rgba(0,0,0,0.03)";
|
|
57695
|
+
const monoFont = `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`;
|
|
57696
|
+
const sansFont = `-apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto, Helvetica, Arial, sans-serif`;
|
|
57697
|
+
const css = `
|
|
57698
|
+
.llm-chat {
|
|
57699
|
+
display: flex;
|
|
57700
|
+
flex-direction: column;
|
|
57701
|
+
border: 1px solid ${border};
|
|
57702
|
+
background: ${bg2};
|
|
57703
|
+
overflow: hidden;
|
|
57704
|
+
font-family: ${sansFont};
|
|
57705
|
+
color: ${text};
|
|
57706
|
+
}
|
|
57707
|
+
|
|
57708
|
+
/* Header */
|
|
57709
|
+
.llm-chat-header {
|
|
57710
|
+
display: flex;
|
|
57711
|
+
align-items: center;
|
|
57712
|
+
justify-content: space-between;
|
|
57713
|
+
padding: 12px 16px;
|
|
57714
|
+
border-bottom: 1px solid ${borderSubtle};
|
|
57715
|
+
}
|
|
57716
|
+
|
|
57717
|
+
/* Model Selector */
|
|
57718
|
+
.llm-chat-model-select {
|
|
57719
|
+
position: relative;
|
|
57720
|
+
}
|
|
57721
|
+
.llm-chat-model-btn {
|
|
57722
|
+
display: flex;
|
|
57723
|
+
align-items: center;
|
|
57724
|
+
gap: 6px;
|
|
57725
|
+
background: transparent;
|
|
57726
|
+
border: none;
|
|
57727
|
+
color: ${text};
|
|
57728
|
+
font-weight: 400;
|
|
57729
|
+
font-size: 11px;
|
|
57730
|
+
font-family: ${monoFont};
|
|
57731
|
+
text-transform: uppercase;
|
|
57732
|
+
letter-spacing: 0.05em;
|
|
57733
|
+
padding: 4px 0;
|
|
57734
|
+
cursor: pointer;
|
|
57735
|
+
transition: opacity 0.1s;
|
|
57736
|
+
}
|
|
57737
|
+
.llm-chat-model-btn:hover {
|
|
57738
|
+
opacity: 0.6;
|
|
57739
|
+
}
|
|
57740
|
+
.llm-chat-model-menu {
|
|
57741
|
+
position: absolute;
|
|
57742
|
+
top: 100%;
|
|
57743
|
+
left: 0;
|
|
57744
|
+
margin-top: 4px;
|
|
57745
|
+
width: 280px;
|
|
57746
|
+
max-height: 300px;
|
|
57747
|
+
overflow-y: auto;
|
|
57748
|
+
background: ${d ? "#0a0a0a" : "#fafafa"};
|
|
57749
|
+
border: 1px solid ${border};
|
|
57750
|
+
z-index: 50;
|
|
57751
|
+
padding: 4px 0;
|
|
57752
|
+
scrollbar-width: thin;
|
|
57753
|
+
}
|
|
57754
|
+
.llm-chat-model-group {
|
|
57755
|
+
padding: 8px 12px 4px;
|
|
57756
|
+
font-size: 10px;
|
|
57757
|
+
font-weight: 400;
|
|
57758
|
+
color: ${textSecondary};
|
|
57759
|
+
text-transform: uppercase;
|
|
57760
|
+
letter-spacing: 0.08em;
|
|
57761
|
+
font-family: ${monoFont};
|
|
57762
|
+
}
|
|
57763
|
+
.llm-chat-model-item {
|
|
57764
|
+
display: block;
|
|
57765
|
+
width: 100%;
|
|
57766
|
+
text-align: left;
|
|
57767
|
+
padding: 6px 12px;
|
|
57768
|
+
font-size: 12px;
|
|
57769
|
+
font-family: ${monoFont};
|
|
57770
|
+
color: ${textSecondary};
|
|
57771
|
+
background: transparent;
|
|
57772
|
+
border: none;
|
|
57773
|
+
cursor: pointer;
|
|
57774
|
+
white-space: nowrap;
|
|
57775
|
+
overflow: hidden;
|
|
57776
|
+
text-overflow: ellipsis;
|
|
57777
|
+
transition: color 0.1s;
|
|
57778
|
+
}
|
|
57779
|
+
.llm-chat-model-item:hover {
|
|
57780
|
+
color: ${text};
|
|
57781
|
+
}
|
|
57782
|
+
.llm-chat-model-item--active {
|
|
57783
|
+
color: ${text};
|
|
57784
|
+
}
|
|
57785
|
+
|
|
57786
|
+
/* Status */
|
|
57787
|
+
.llm-chat-status {
|
|
57788
|
+
display: flex;
|
|
57789
|
+
align-items: center;
|
|
57790
|
+
gap: 8px;
|
|
57791
|
+
font-size: 10px;
|
|
57792
|
+
font-family: ${monoFont};
|
|
57793
|
+
text-transform: uppercase;
|
|
57794
|
+
letter-spacing: 0.08em;
|
|
57795
|
+
color: ${textSecondary};
|
|
57796
|
+
}
|
|
57797
|
+
.llm-chat-dot {
|
|
57798
|
+
width: 5px;
|
|
57799
|
+
height: 5px;
|
|
57800
|
+
border-radius: 50%;
|
|
57801
|
+
}
|
|
57802
|
+
.llm-chat-dot--loading {
|
|
57803
|
+
background: ${textSecondary};
|
|
57804
|
+
animation: llm-pulse 1.5s infinite;
|
|
57805
|
+
}
|
|
57806
|
+
.llm-chat-dot--ready {
|
|
57807
|
+
background: ${text};
|
|
57808
|
+
}
|
|
57809
|
+
.llm-chat-dot--error {
|
|
57810
|
+
background: #ff3333;
|
|
57811
|
+
}
|
|
57812
|
+
|
|
57813
|
+
/* Progress */
|
|
57814
|
+
.llm-chat-progress {
|
|
57815
|
+
padding: 0 16px 8px;
|
|
57816
|
+
}
|
|
57817
|
+
.llm-chat-progress-bar {
|
|
57818
|
+
height: 1px;
|
|
57819
|
+
background: ${borderSubtle};
|
|
57820
|
+
overflow: hidden;
|
|
57821
|
+
}
|
|
57822
|
+
.llm-chat-progress-fill {
|
|
57823
|
+
height: 100%;
|
|
57824
|
+
background: ${text};
|
|
57825
|
+
transition: width 0.3s ease;
|
|
57826
|
+
}
|
|
57827
|
+
.llm-chat-progress-text {
|
|
57828
|
+
font-size: 10px;
|
|
57829
|
+
font-family: ${monoFont};
|
|
57830
|
+
color: ${textTertiary};
|
|
57831
|
+
margin-top: 4px;
|
|
57832
|
+
text-align: right;
|
|
57833
|
+
text-transform: uppercase;
|
|
57834
|
+
letter-spacing: 0.05em;
|
|
57835
|
+
}
|
|
57836
|
+
|
|
57837
|
+
/* Messages */
|
|
57838
|
+
.llm-chat-messages {
|
|
57839
|
+
flex: 1;
|
|
57840
|
+
overflow-y: auto;
|
|
57841
|
+
padding: 20px 16px;
|
|
57842
|
+
display: flex;
|
|
57843
|
+
flex-direction: column;
|
|
57844
|
+
gap: 24px;
|
|
57845
|
+
scrollbar-width: thin;
|
|
57846
|
+
}
|
|
57847
|
+
|
|
57848
|
+
/* Welcome */
|
|
57849
|
+
.llm-chat-welcome {
|
|
57850
|
+
display: flex;
|
|
57851
|
+
flex-direction: column;
|
|
57852
|
+
align-items: flex-start;
|
|
57853
|
+
justify-content: center;
|
|
57854
|
+
flex: 1;
|
|
57855
|
+
color: ${textTertiary};
|
|
57856
|
+
padding: 40px 0;
|
|
57857
|
+
}
|
|
57858
|
+
.llm-chat-welcome h3 {
|
|
57859
|
+
font-size: 11px;
|
|
57860
|
+
font-weight: 400;
|
|
57861
|
+
font-family: ${monoFont};
|
|
57862
|
+
text-transform: uppercase;
|
|
57863
|
+
letter-spacing: 0.08em;
|
|
57864
|
+
color: ${textSecondary};
|
|
57865
|
+
margin: 0 0 8px;
|
|
57866
|
+
}
|
|
57867
|
+
.llm-chat-welcome p {
|
|
57868
|
+
font-size: 13px;
|
|
57869
|
+
margin: 0;
|
|
57870
|
+
max-width: 360px;
|
|
57871
|
+
line-height: 1.6;
|
|
57872
|
+
color: ${textTertiary};
|
|
57873
|
+
}
|
|
57874
|
+
|
|
57875
|
+
/* Bubble */
|
|
57876
|
+
.llm-chat-bubble {
|
|
57877
|
+
display: flex;
|
|
57878
|
+
flex-direction: column;
|
|
57879
|
+
max-width: 100%;
|
|
57880
|
+
}
|
|
57881
|
+
.llm-chat-bubble--user {
|
|
57882
|
+
align-self: flex-end;
|
|
57883
|
+
max-width: 80%;
|
|
57884
|
+
}
|
|
57885
|
+
.llm-chat-bubble--assistant {
|
|
57886
|
+
align-self: flex-start;
|
|
57887
|
+
width: 100%;
|
|
57888
|
+
}
|
|
57889
|
+
|
|
57890
|
+
/* User message — flat, subtle bg, no radius */
|
|
57891
|
+
.llm-chat-user-content {
|
|
57892
|
+
padding: 10px 14px;
|
|
57893
|
+
font-size: 14px;
|
|
57894
|
+
line-height: 1.6;
|
|
57895
|
+
white-space: pre-wrap;
|
|
57896
|
+
background: ${surfaceSubtle};
|
|
57897
|
+
border: 1px solid ${borderSubtle};
|
|
57898
|
+
color: ${text};
|
|
57899
|
+
}
|
|
57900
|
+
|
|
57901
|
+
/* Assistant message */
|
|
57902
|
+
.llm-chat-assistant-content {
|
|
57903
|
+
font-size: 14px;
|
|
57904
|
+
line-height: 1.7;
|
|
57905
|
+
color: ${d ? "rgba(255,255,255,0.85)" : "rgba(0,0,0,0.85)"};
|
|
57906
|
+
}
|
|
57907
|
+
|
|
57908
|
+
/* Streamdown Overrides */
|
|
57909
|
+
.llm-chat-assistant-content pre {
|
|
57910
|
+
background: ${surfaceSubtle} !important;
|
|
57911
|
+
border: 1px solid ${borderSubtle} !important;
|
|
57912
|
+
border-radius: 0 !important;
|
|
57913
|
+
padding: 12px !important;
|
|
57914
|
+
margin: 12px 0 !important;
|
|
57915
|
+
}
|
|
57916
|
+
.llm-chat-assistant-content code {
|
|
57917
|
+
font-family: ${monoFont} !important;
|
|
57918
|
+
font-size: 13px !important;
|
|
57919
|
+
}
|
|
57920
|
+
.llm-chat-assistant-content :not(pre) > code {
|
|
57921
|
+
background: ${surfaceSubtle};
|
|
57922
|
+
border: 1px solid ${borderSubtle};
|
|
57923
|
+
padding: 1px 5px;
|
|
57924
|
+
font-size: 12.5px !important;
|
|
57925
|
+
}
|
|
57926
|
+
|
|
57927
|
+
/* Attachments in message */
|
|
57928
|
+
.llm-chat-msg-images {
|
|
57929
|
+
display: flex;
|
|
57930
|
+
flex-wrap: wrap;
|
|
57931
|
+
gap: 6px;
|
|
57932
|
+
margin-bottom: 8px;
|
|
57933
|
+
justify-content: flex-end;
|
|
57934
|
+
}
|
|
57935
|
+
.llm-chat-msg-img {
|
|
57936
|
+
width: 100px;
|
|
57937
|
+
height: 100px;
|
|
57938
|
+
object-fit: cover;
|
|
57939
|
+
border: 1px solid ${border};
|
|
57940
|
+
}
|
|
57941
|
+
|
|
57942
|
+
/* Error */
|
|
57943
|
+
.llm-chat-error {
|
|
57944
|
+
margin: 0 16px;
|
|
57945
|
+
padding: 10px 14px;
|
|
57946
|
+
border: 1px solid ${d ? "rgba(255,50,50,0.2)" : "rgba(200,0,0,0.15)"};
|
|
57947
|
+
display: flex;
|
|
57948
|
+
align-items: center;
|
|
57949
|
+
justify-content: space-between;
|
|
57950
|
+
gap: 12px;
|
|
57951
|
+
}
|
|
57952
|
+
.llm-chat-error-text {
|
|
57953
|
+
font-size: 12px;
|
|
57954
|
+
font-family: ${monoFont};
|
|
57955
|
+
color: ${d ? "#ff6666" : "#cc0000"};
|
|
57956
|
+
flex: 1;
|
|
57957
|
+
}
|
|
57958
|
+
.llm-chat-error-retry {
|
|
57959
|
+
display: flex;
|
|
57960
|
+
align-items: center;
|
|
57961
|
+
gap: 4px;
|
|
57962
|
+
padding: 4px 10px;
|
|
57963
|
+
border: 1px solid ${d ? "rgba(255,50,50,0.3)" : "rgba(200,0,0,0.2)"};
|
|
57964
|
+
background: transparent;
|
|
57965
|
+
color: ${d ? "#ff6666" : "#cc0000"};
|
|
57966
|
+
font-size: 11px;
|
|
57967
|
+
font-family: ${monoFont};
|
|
57968
|
+
text-transform: uppercase;
|
|
57969
|
+
letter-spacing: 0.05em;
|
|
57970
|
+
cursor: pointer;
|
|
57971
|
+
}
|
|
57972
|
+
.llm-chat-error-retry:hover {
|
|
57973
|
+
background: ${d ? "rgba(255,50,50,0.08)" : "rgba(200,0,0,0.04)"};
|
|
57974
|
+
}
|
|
57975
|
+
|
|
57976
|
+
/* Input Area */
|
|
57977
|
+
.llm-chat-input-area {
|
|
57978
|
+
padding: 12px 16px 16px;
|
|
57979
|
+
border-top: 1px solid ${borderSubtle};
|
|
57980
|
+
}
|
|
57981
|
+
|
|
57982
|
+
@keyframes llm-pulse {
|
|
57983
|
+
0%, 100% { opacity: 1; }
|
|
57984
|
+
50% { opacity: 0.2; }
|
|
57985
|
+
}
|
|
57986
|
+
`;
|
|
57987
|
+
const style = document.createElement("style");
|
|
57988
|
+
style.id = STYLE_ID2;
|
|
57989
|
+
style.textContent = css;
|
|
57990
|
+
document.head.appendChild(style);
|
|
57991
|
+
}
|
|
57992
|
+
function ModelSelector({
|
|
57993
|
+
currentModel,
|
|
57994
|
+
onSelect,
|
|
57995
|
+
theme
|
|
57996
|
+
}) {
|
|
57997
|
+
const [isOpen, setIsOpen] = useState2(false);
|
|
57998
|
+
const ref = useRef2(null);
|
|
57999
|
+
useEffect2(() => {
|
|
58000
|
+
function handleClickOutside(event) {
|
|
58001
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
58002
|
+
setIsOpen(false);
|
|
58003
|
+
}
|
|
58004
|
+
}
|
|
58005
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
58006
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
58007
|
+
}, []);
|
|
58008
|
+
const displayModel = useMemo(() => {
|
|
58009
|
+
if (!currentModel)
|
|
58010
|
+
return "Select Model";
|
|
58011
|
+
const id2 = currentModel.split("/").pop() || currentModel;
|
|
58012
|
+
return id2.length > 25 ? id2.substring(0, 25) + "..." : id2;
|
|
58013
|
+
}, [currentModel]);
|
|
58014
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
58015
|
+
className: "llm-chat-model-select",
|
|
58016
|
+
ref,
|
|
58017
|
+
children: [
|
|
58018
|
+
/* @__PURE__ */ jsxDEV2("button", {
|
|
58019
|
+
type: "button",
|
|
58020
|
+
className: "llm-chat-model-btn",
|
|
58021
|
+
onClick: () => setIsOpen(!isOpen),
|
|
58022
|
+
children: [
|
|
58023
|
+
"[",
|
|
58024
|
+
displayModel,
|
|
58025
|
+
"] ",
|
|
58026
|
+
/* @__PURE__ */ jsxDEV2(ChevronDownIcon, {}, undefined, false, undefined, this)
|
|
58027
|
+
]
|
|
58028
|
+
}, undefined, true, undefined, this),
|
|
58029
|
+
isOpen && /* @__PURE__ */ jsxDEV2("div", {
|
|
58030
|
+
className: "llm-chat-model-menu",
|
|
58031
|
+
children: [
|
|
58032
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58033
|
+
className: "llm-chat-model-group",
|
|
58034
|
+
children: "[WebLLM]"
|
|
58035
|
+
}, undefined, false, undefined, this),
|
|
58036
|
+
Object.entries(WEBLLM_MODELS).map(([key, value]) => /* @__PURE__ */ jsxDEV2("button", {
|
|
58037
|
+
className: `llm-chat-model-item ${currentModel === value ? "llm-chat-model-item--active" : ""}`,
|
|
58038
|
+
onClick: () => {
|
|
58039
|
+
onSelect(value);
|
|
58040
|
+
setIsOpen(false);
|
|
58041
|
+
},
|
|
58042
|
+
children: key
|
|
58043
|
+
}, key, false, undefined, this)),
|
|
58044
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58045
|
+
className: "llm-chat-model-group",
|
|
58046
|
+
children: "[Transformers.js]"
|
|
58047
|
+
}, undefined, false, undefined, this),
|
|
58048
|
+
Object.entries(TRANSFORMERS_MODELS).map(([key, value]) => /* @__PURE__ */ jsxDEV2("button", {
|
|
58049
|
+
className: `llm-chat-model-item ${currentModel === value ? "llm-chat-model-item--active" : ""}`,
|
|
58050
|
+
onClick: () => {
|
|
58051
|
+
onSelect(value);
|
|
58052
|
+
setIsOpen(false);
|
|
58053
|
+
},
|
|
58054
|
+
children: key
|
|
58055
|
+
}, key, false, undefined, this))
|
|
58056
|
+
]
|
|
58057
|
+
}, undefined, true, undefined, this)
|
|
58058
|
+
]
|
|
58059
|
+
}, undefined, true, undefined, this);
|
|
58060
|
+
}
|
|
58061
|
+
function Chat2({
|
|
58062
|
+
systemPrompt = DEFAULT_SYSTEM_PROMPT,
|
|
58063
|
+
placeholder = "Type a message...",
|
|
58064
|
+
theme = "dark",
|
|
58065
|
+
className,
|
|
58066
|
+
maxHeight = "600px",
|
|
58067
|
+
inputActions,
|
|
58068
|
+
onSend: onSendProp,
|
|
58069
|
+
onResponse,
|
|
58070
|
+
onError: onErrorProp,
|
|
58071
|
+
showHeader = true,
|
|
58072
|
+
showProgress = true,
|
|
58073
|
+
welcomeMessage = "Ready to assist",
|
|
58074
|
+
onModelChange
|
|
58075
|
+
}) {
|
|
58076
|
+
const { llm, isLoading, isReady, loadProgress, error, modelId, reload } = useLLM();
|
|
58077
|
+
const [messages, setMessages] = useState2([]);
|
|
58078
|
+
const [input, setInput] = useState2("");
|
|
58079
|
+
const [isGenerating, setIsGenerating] = useState2(false);
|
|
58080
|
+
const [streamingText, setStreamingText] = useState2("");
|
|
58081
|
+
const [pendingMessage, setPendingMessage] = useState2(null);
|
|
58082
|
+
const [images, setImages] = useState2([]);
|
|
58083
|
+
const messagesEndRef = useRef2(null);
|
|
58084
|
+
const abortRef = useRef2(false);
|
|
58085
|
+
const isProcessingRef = useRef2(false);
|
|
58086
|
+
useEffect2(() => {
|
|
58087
|
+
injectChatStyles(theme);
|
|
58088
|
+
}, [theme]);
|
|
58089
|
+
useEffect2(() => {
|
|
58090
|
+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
58091
|
+
}, [messages, streamingText, isGenerating]);
|
|
58092
|
+
const generate = async (userContent, currentMessages, attachedImages = []) => {
|
|
58093
|
+
if (!llm || !isReady || isProcessingRef.current)
|
|
58094
|
+
return;
|
|
58095
|
+
isProcessingRef.current = true;
|
|
58096
|
+
const userMsg = {
|
|
58097
|
+
role: "user",
|
|
58098
|
+
content: userContent,
|
|
58099
|
+
images: attachedImages
|
|
58100
|
+
};
|
|
58101
|
+
setMessages((prev) => [...prev, userMsg]);
|
|
58102
|
+
setIsGenerating(true);
|
|
58103
|
+
setStreamingText("");
|
|
58104
|
+
abortRef.current = false;
|
|
58105
|
+
const apiMessages = [];
|
|
58106
|
+
if (systemPrompt) {
|
|
58107
|
+
apiMessages.push({ role: "system", content: systemPrompt });
|
|
58108
|
+
}
|
|
58109
|
+
currentMessages.forEach((m) => {
|
|
58110
|
+
apiMessages.push({ role: m.role, content: m.content });
|
|
58111
|
+
});
|
|
58112
|
+
apiMessages.push({ role: "user", content: userContent });
|
|
58113
|
+
try {
|
|
58114
|
+
const response = await llm.stream(apiMessages, (_token, fullText) => {
|
|
58115
|
+
if (abortRef.current)
|
|
58116
|
+
return;
|
|
58117
|
+
setStreamingText(fullText);
|
|
58118
|
+
});
|
|
58119
|
+
if (!abortRef.current) {
|
|
58120
|
+
const assistantMsg = { role: "assistant", content: response };
|
|
58121
|
+
setMessages((prev) => [...prev, assistantMsg]);
|
|
58122
|
+
setStreamingText("");
|
|
58123
|
+
onResponse?.(response);
|
|
58124
|
+
}
|
|
58125
|
+
} catch (err) {
|
|
58126
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
58127
|
+
onErrorProp?.(error2);
|
|
58128
|
+
setMessages((prev) => [...prev, {
|
|
58129
|
+
role: "assistant",
|
|
58130
|
+
content: `Error: ${error2.message}`
|
|
58131
|
+
}]);
|
|
58132
|
+
} finally {
|
|
58133
|
+
setIsGenerating(false);
|
|
58134
|
+
isProcessingRef.current = false;
|
|
58135
|
+
}
|
|
58136
|
+
};
|
|
58137
|
+
const handleSend = () => {
|
|
58138
|
+
const text = input.trim();
|
|
58139
|
+
if (!text && images.length === 0)
|
|
58140
|
+
return;
|
|
58141
|
+
const currentImages = [...images];
|
|
58142
|
+
setInput("");
|
|
58143
|
+
setImages([]);
|
|
58144
|
+
onSendProp?.(text);
|
|
58145
|
+
if (llm && isReady) {
|
|
58146
|
+
generate(text, messages, currentImages);
|
|
58147
|
+
} else if (isLoading) {
|
|
58148
|
+
setPendingMessage(text);
|
|
58149
|
+
}
|
|
58150
|
+
};
|
|
58151
|
+
const handleStop = () => {
|
|
58152
|
+
abortRef.current = true;
|
|
58153
|
+
setIsGenerating(false);
|
|
58154
|
+
if (streamingText) {
|
|
58155
|
+
setMessages((prev) => [...prev, { role: "assistant", content: streamingText + "..." }]);
|
|
58156
|
+
setStreamingText("");
|
|
58157
|
+
}
|
|
58158
|
+
};
|
|
58159
|
+
const statusDotClass = error ? "llm-chat-dot llm-chat-dot--error" : isReady ? "llm-chat-dot llm-chat-dot--ready" : "llm-chat-dot llm-chat-dot--loading";
|
|
58160
|
+
const statusText = error ? "Error" : isReady ? "Ready" : isLoading ? "Loading" : "Idle";
|
|
58161
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
58162
|
+
className: `llm-chat${className ? ` ${className}` : ""}`,
|
|
58163
|
+
style: { maxHeight, height: "100%" },
|
|
58164
|
+
children: [
|
|
58165
|
+
showHeader && /* @__PURE__ */ jsxDEV2("div", {
|
|
58166
|
+
className: "llm-chat-header",
|
|
58167
|
+
children: [
|
|
58168
|
+
onModelChange ? /* @__PURE__ */ jsxDEV2(ModelSelector, {
|
|
58169
|
+
currentModel: modelId,
|
|
58170
|
+
onSelect: onModelChange,
|
|
58171
|
+
theme
|
|
58172
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2("div", {
|
|
58173
|
+
className: "llm-chat-model-select",
|
|
58174
|
+
children: /* @__PURE__ */ jsxDEV2("span", {
|
|
58175
|
+
style: {
|
|
58176
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
58177
|
+
fontSize: "11px",
|
|
58178
|
+
textTransform: "uppercase",
|
|
58179
|
+
letterSpacing: "0.05em"
|
|
58180
|
+
},
|
|
58181
|
+
children: [
|
|
58182
|
+
"[",
|
|
58183
|
+
modelId?.split("/").pop(),
|
|
58184
|
+
"]"
|
|
58185
|
+
]
|
|
58186
|
+
}, undefined, true, undefined, this)
|
|
58187
|
+
}, undefined, false, undefined, this),
|
|
58188
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58189
|
+
className: "llm-chat-status",
|
|
58190
|
+
children: [
|
|
58191
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
58192
|
+
children: statusText
|
|
58193
|
+
}, undefined, false, undefined, this),
|
|
58194
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58195
|
+
className: statusDotClass
|
|
58196
|
+
}, undefined, false, undefined, this)
|
|
58197
|
+
]
|
|
58198
|
+
}, undefined, true, undefined, this)
|
|
58199
|
+
]
|
|
58200
|
+
}, undefined, true, undefined, this),
|
|
58201
|
+
showProgress && isLoading && loadProgress && /* @__PURE__ */ jsxDEV2("div", {
|
|
58202
|
+
className: "llm-chat-progress",
|
|
58203
|
+
children: [
|
|
58204
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58205
|
+
className: "llm-chat-progress-bar",
|
|
58206
|
+
children: /* @__PURE__ */ jsxDEV2("div", {
|
|
58207
|
+
className: "llm-chat-progress-fill",
|
|
58208
|
+
style: { width: `${Math.min(100, loadProgress.progress)}%` }
|
|
58209
|
+
}, undefined, false, undefined, this)
|
|
58210
|
+
}, undefined, false, undefined, this),
|
|
58211
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58212
|
+
className: "llm-chat-progress-text",
|
|
58213
|
+
children: loadProgress.status
|
|
58214
|
+
}, undefined, false, undefined, this)
|
|
58215
|
+
]
|
|
58216
|
+
}, undefined, true, undefined, this),
|
|
58217
|
+
error && /* @__PURE__ */ jsxDEV2("div", {
|
|
58218
|
+
className: "llm-chat-error",
|
|
58219
|
+
children: [
|
|
58220
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
58221
|
+
className: "llm-chat-error-text",
|
|
58222
|
+
children: error.message
|
|
58223
|
+
}, undefined, false, undefined, this),
|
|
58224
|
+
/* @__PURE__ */ jsxDEV2("button", {
|
|
58225
|
+
className: "llm-chat-error-retry",
|
|
58226
|
+
onClick: reload,
|
|
58227
|
+
children: [
|
|
58228
|
+
/* @__PURE__ */ jsxDEV2(RetryIcon, {}, undefined, false, undefined, this),
|
|
58229
|
+
" Retry"
|
|
58230
|
+
]
|
|
58231
|
+
}, undefined, true, undefined, this)
|
|
58232
|
+
]
|
|
58233
|
+
}, undefined, true, undefined, this),
|
|
58234
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58235
|
+
className: "llm-chat-messages",
|
|
58236
|
+
children: [
|
|
58237
|
+
!isLoading && messages.length === 0 && !error && /* @__PURE__ */ jsxDEV2("div", {
|
|
58238
|
+
className: "llm-chat-welcome",
|
|
58239
|
+
children: [
|
|
58240
|
+
/* @__PURE__ */ jsxDEV2("h3", {
|
|
58241
|
+
children: [
|
|
58242
|
+
"[",
|
|
58243
|
+
welcomeMessage,
|
|
58244
|
+
"]"
|
|
58245
|
+
]
|
|
58246
|
+
}, undefined, true, undefined, this),
|
|
58247
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
58248
|
+
children: "Markdown, code blocks, Mermaid diagrams. Paste images with Ctrl+V."
|
|
58249
|
+
}, undefined, false, undefined, this)
|
|
58250
|
+
]
|
|
58251
|
+
}, undefined, true, undefined, this),
|
|
58252
|
+
messages.map((msg, i) => /* @__PURE__ */ jsxDEV2("div", {
|
|
58253
|
+
className: `llm-chat-bubble llm-chat-bubble--${msg.role}`,
|
|
58254
|
+
children: msg.role === "user" ? /* @__PURE__ */ jsxDEV2(Fragment2, {
|
|
58255
|
+
children: [
|
|
58256
|
+
msg.images && msg.images.length > 0 && /* @__PURE__ */ jsxDEV2("div", {
|
|
58257
|
+
className: "llm-chat-msg-images",
|
|
58258
|
+
children: msg.images.map((img) => /* @__PURE__ */ jsxDEV2("img", {
|
|
58259
|
+
src: img.dataUrl,
|
|
58260
|
+
className: "llm-chat-msg-img",
|
|
58261
|
+
alt: "attachment"
|
|
58262
|
+
}, img.id, false, undefined, this))
|
|
58263
|
+
}, undefined, false, undefined, this),
|
|
58264
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58265
|
+
className: "llm-chat-user-content",
|
|
58266
|
+
children: msg.content
|
|
58267
|
+
}, undefined, false, undefined, this)
|
|
58268
|
+
]
|
|
58269
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV2("div", {
|
|
58270
|
+
className: "llm-chat-assistant-content",
|
|
58271
|
+
children: /* @__PURE__ */ jsxDEV2(Streamdown, {
|
|
58272
|
+
plugins: { code, mermaid },
|
|
58273
|
+
children: msg.content
|
|
58274
|
+
}, undefined, false, undefined, this)
|
|
58275
|
+
}, undefined, false, undefined, this)
|
|
58276
|
+
}, i, false, undefined, this)),
|
|
58277
|
+
streamingText && /* @__PURE__ */ jsxDEV2("div", {
|
|
58278
|
+
className: "llm-chat-bubble llm-chat-bubble--assistant",
|
|
58279
|
+
children: /* @__PURE__ */ jsxDEV2("div", {
|
|
58280
|
+
className: "llm-chat-assistant-content",
|
|
58281
|
+
children: /* @__PURE__ */ jsxDEV2(Streamdown, {
|
|
58282
|
+
plugins: { code, mermaid },
|
|
58283
|
+
children: streamingText
|
|
58284
|
+
}, undefined, false, undefined, this)
|
|
58285
|
+
}, undefined, false, undefined, this)
|
|
58286
|
+
}, undefined, false, undefined, this),
|
|
58287
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58288
|
+
ref: messagesEndRef
|
|
58289
|
+
}, undefined, false, undefined, this)
|
|
58290
|
+
]
|
|
58291
|
+
}, undefined, true, undefined, this),
|
|
58292
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
58293
|
+
className: "llm-chat-input-area",
|
|
58294
|
+
children: /* @__PURE__ */ jsxDEV2(ChatInput, {
|
|
58295
|
+
value: input,
|
|
58296
|
+
onChange: setInput,
|
|
58297
|
+
onSend: handleSend,
|
|
58298
|
+
onStop: handleStop,
|
|
58299
|
+
disabled: !isReady && !isLoading,
|
|
58300
|
+
isGenerating,
|
|
58301
|
+
placeholder: isLoading ? "Model is loading..." : placeholder,
|
|
58302
|
+
theme,
|
|
58303
|
+
actions: inputActions,
|
|
58304
|
+
images,
|
|
58305
|
+
onImageAdd: (img) => setImages((prev) => [...prev, img]),
|
|
58306
|
+
onImageRemove: (id2) => setImages((prev) => prev.filter((img) => img.id !== id2))
|
|
58307
|
+
}, undefined, false, undefined, this)
|
|
58308
|
+
}, undefined, false, undefined, this)
|
|
58309
|
+
]
|
|
58310
|
+
}, undefined, true, undefined, this);
|
|
58311
|
+
}
|
|
58312
|
+
|
|
58313
|
+
// src/react/index.tsx
|
|
58314
|
+
import { jsxDEV as jsxDEV3, Fragment as Fragment3 } from "react/jsx-dev-runtime";
|
|
57137
58315
|
var LLMContext = createContext(null);
|
|
57138
58316
|
function LLMProvider({
|
|
57139
58317
|
children,
|
|
@@ -57143,14 +58321,14 @@ function LLMProvider({
|
|
|
57143
58321
|
onError,
|
|
57144
58322
|
...config
|
|
57145
58323
|
}) {
|
|
57146
|
-
const [llm, setLLM] =
|
|
57147
|
-
const [isLoading, setIsLoading] =
|
|
57148
|
-
const [loadProgress, setLoadProgress] =
|
|
57149
|
-
const [error, setError] =
|
|
57150
|
-
const hasLoadedRef =
|
|
57151
|
-
const configRef =
|
|
58324
|
+
const [llm, setLLM] = useState3(null);
|
|
58325
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
58326
|
+
const [loadProgress, setLoadProgress] = useState3(null);
|
|
58327
|
+
const [error, setError] = useState3(null);
|
|
58328
|
+
const hasLoadedRef = useRef3(false);
|
|
58329
|
+
const configRef = useRef3(config);
|
|
57152
58330
|
configRef.current = config;
|
|
57153
|
-
const load =
|
|
58331
|
+
const load = useCallback2(async () => {
|
|
57154
58332
|
if (isLoading)
|
|
57155
58333
|
return;
|
|
57156
58334
|
setIsLoading(true);
|
|
@@ -57175,7 +58353,7 @@ function LLMProvider({
|
|
|
57175
58353
|
setIsLoading(false);
|
|
57176
58354
|
}
|
|
57177
58355
|
}, [isLoading, onLoad, onProgress, onError]);
|
|
57178
|
-
const unload =
|
|
58356
|
+
const unload = useCallback2(async () => {
|
|
57179
58357
|
if (llm) {
|
|
57180
58358
|
await llm.unload();
|
|
57181
58359
|
setLLM(null);
|
|
@@ -57183,24 +58361,24 @@ function LLMProvider({
|
|
|
57183
58361
|
hasLoadedRef.current = false;
|
|
57184
58362
|
}
|
|
57185
58363
|
}, [llm]);
|
|
57186
|
-
const reload =
|
|
58364
|
+
const reload = useCallback2(async () => {
|
|
57187
58365
|
await unload();
|
|
57188
58366
|
await load();
|
|
57189
58367
|
}, [unload, load]);
|
|
57190
|
-
|
|
58368
|
+
useEffect3(() => {
|
|
57191
58369
|
if (autoLoad && !hasLoadedRef.current && !llm && !isLoading) {
|
|
57192
58370
|
hasLoadedRef.current = true;
|
|
57193
58371
|
load();
|
|
57194
58372
|
}
|
|
57195
58373
|
}, [autoLoad, llm, isLoading, load]);
|
|
57196
|
-
|
|
58374
|
+
useEffect3(() => {
|
|
57197
58375
|
return () => {
|
|
57198
58376
|
if (llm) {
|
|
57199
58377
|
llm.unload().catch(console.error);
|
|
57200
58378
|
}
|
|
57201
58379
|
};
|
|
57202
58380
|
}, [llm]);
|
|
57203
|
-
const value =
|
|
58381
|
+
const value = useMemo2(() => ({
|
|
57204
58382
|
llm,
|
|
57205
58383
|
isLoading,
|
|
57206
58384
|
isReady: llm?.isReady ?? false,
|
|
@@ -57211,7 +58389,7 @@ function LLMProvider({
|
|
|
57211
58389
|
reload,
|
|
57212
58390
|
unload
|
|
57213
58391
|
}), [llm, isLoading, loadProgress, error, reload, unload]);
|
|
57214
|
-
return /* @__PURE__ */
|
|
58392
|
+
return /* @__PURE__ */ jsxDEV3(LLMContext.Provider, {
|
|
57215
58393
|
value,
|
|
57216
58394
|
children
|
|
57217
58395
|
}, undefined, false, undefined, this);
|
|
@@ -57235,14 +58413,14 @@ function useChat(options = {}) {
|
|
|
57235
58413
|
onFinish,
|
|
57236
58414
|
onError
|
|
57237
58415
|
} = options;
|
|
57238
|
-
const [messages, setMessages] =
|
|
57239
|
-
const [input, setInput] =
|
|
57240
|
-
const [isGenerating, setIsGenerating] =
|
|
57241
|
-
const [streamingText, setStreamingText] =
|
|
57242
|
-
const [pendingMessage, setPendingMessage] =
|
|
57243
|
-
const abortRef =
|
|
57244
|
-
const isProcessingRef =
|
|
57245
|
-
const generateResponse =
|
|
58416
|
+
const [messages, setMessages] = useState3(initialMessages);
|
|
58417
|
+
const [input, setInput] = useState3("");
|
|
58418
|
+
const [isGenerating, setIsGenerating] = useState3(false);
|
|
58419
|
+
const [streamingText, setStreamingText] = useState3("");
|
|
58420
|
+
const [pendingMessage, setPendingMessage] = useState3(null);
|
|
58421
|
+
const abortRef = useRef3(false);
|
|
58422
|
+
const isProcessingRef = useRef3(false);
|
|
58423
|
+
const generateResponse = useCallback2(async (userContent, currentMessages) => {
|
|
57246
58424
|
if (!llm || !isReady || isProcessingRef.current) {
|
|
57247
58425
|
return "";
|
|
57248
58426
|
}
|
|
@@ -57284,14 +58462,14 @@ function useChat(options = {}) {
|
|
|
57284
58462
|
isProcessingRef.current = false;
|
|
57285
58463
|
}
|
|
57286
58464
|
}, [llm, isReady, systemPrompt, generateOptions, onStart, onToken, onFinish, onError]);
|
|
57287
|
-
|
|
58465
|
+
useEffect3(() => {
|
|
57288
58466
|
if (isReady && pendingMessage && !isProcessingRef.current) {
|
|
57289
58467
|
const messageToProcess = pendingMessage;
|
|
57290
58468
|
setPendingMessage(null);
|
|
57291
58469
|
generateResponse(messageToProcess, messages);
|
|
57292
58470
|
}
|
|
57293
58471
|
}, [isReady, pendingMessage, messages, generateResponse]);
|
|
57294
|
-
const send =
|
|
58472
|
+
const send = useCallback2(async (content) => {
|
|
57295
58473
|
const messageContent = content ?? input;
|
|
57296
58474
|
if (!messageContent.trim()) {
|
|
57297
58475
|
return "";
|
|
@@ -57310,7 +58488,7 @@ function useChat(options = {}) {
|
|
|
57310
58488
|
}
|
|
57311
58489
|
return "";
|
|
57312
58490
|
}, [input, llm, isReady, isLoading, queueWhileLoading, messages, generateResponse]);
|
|
57313
|
-
const stop =
|
|
58491
|
+
const stop = useCallback2(() => {
|
|
57314
58492
|
abortRef.current = true;
|
|
57315
58493
|
setIsGenerating(false);
|
|
57316
58494
|
setPendingMessage(null);
|
|
@@ -57322,16 +58500,16 @@ function useChat(options = {}) {
|
|
|
57322
58500
|
setStreamingText("");
|
|
57323
58501
|
}
|
|
57324
58502
|
}, [streamingText]);
|
|
57325
|
-
const clear =
|
|
58503
|
+
const clear = useCallback2(() => {
|
|
57326
58504
|
setMessages(initialMessages);
|
|
57327
58505
|
setStreamingText("");
|
|
57328
58506
|
setInput("");
|
|
57329
58507
|
setPendingMessage(null);
|
|
57330
58508
|
}, [initialMessages]);
|
|
57331
|
-
const append =
|
|
58509
|
+
const append = useCallback2((message) => {
|
|
57332
58510
|
setMessages((prev) => [...prev, message]);
|
|
57333
58511
|
}, []);
|
|
57334
|
-
const reload =
|
|
58512
|
+
const reload = useCallback2(async () => {
|
|
57335
58513
|
if (messages.length === 0)
|
|
57336
58514
|
return "";
|
|
57337
58515
|
const lastUserIndex = messages.findLastIndex((m) => m.role === "user");
|
|
@@ -57361,10 +58539,10 @@ function useChat(options = {}) {
|
|
|
57361
58539
|
function useStream(options = {}) {
|
|
57362
58540
|
const { llm, isReady } = useLLM();
|
|
57363
58541
|
const { generateOptions, onToken, onFinish, onError } = options;
|
|
57364
|
-
const [text, setText] =
|
|
57365
|
-
const [isStreaming, setIsStreaming] =
|
|
57366
|
-
const abortRef =
|
|
57367
|
-
const stream =
|
|
58542
|
+
const [text, setText] = useState3("");
|
|
58543
|
+
const [isStreaming, setIsStreaming] = useState3(false);
|
|
58544
|
+
const abortRef = useRef3(false);
|
|
58545
|
+
const stream = useCallback2(async (input) => {
|
|
57368
58546
|
if (!llm || !isReady) {
|
|
57369
58547
|
return "";
|
|
57370
58548
|
}
|
|
@@ -57388,11 +58566,11 @@ function useStream(options = {}) {
|
|
|
57388
58566
|
setIsStreaming(false);
|
|
57389
58567
|
}
|
|
57390
58568
|
}, [llm, isReady, generateOptions, onToken, onFinish, onError]);
|
|
57391
|
-
const stop =
|
|
58569
|
+
const stop = useCallback2(() => {
|
|
57392
58570
|
abortRef.current = true;
|
|
57393
58571
|
setIsStreaming(false);
|
|
57394
58572
|
}, []);
|
|
57395
|
-
const clear =
|
|
58573
|
+
const clear = useCallback2(() => {
|
|
57396
58574
|
setText("");
|
|
57397
58575
|
}, []);
|
|
57398
58576
|
return {
|
|
@@ -57406,9 +58584,9 @@ function useStream(options = {}) {
|
|
|
57406
58584
|
function useCompletion(options = {}) {
|
|
57407
58585
|
const { llm, isReady } = useLLM();
|
|
57408
58586
|
const { generateOptions } = options;
|
|
57409
|
-
const [completion, setCompletion] =
|
|
57410
|
-
const [isLoading, setIsLoading] =
|
|
57411
|
-
const complete =
|
|
58587
|
+
const [completion, setCompletion] = useState3("");
|
|
58588
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
58589
|
+
const complete = useCallback2(async (prompt) => {
|
|
57412
58590
|
if (!llm || !isReady) {
|
|
57413
58591
|
return "";
|
|
57414
58592
|
}
|
|
@@ -57424,7 +58602,7 @@ function useCompletion(options = {}) {
|
|
|
57424
58602
|
setIsLoading(false);
|
|
57425
58603
|
}
|
|
57426
58604
|
}, [llm, isReady, generateOptions]);
|
|
57427
|
-
const clear =
|
|
58605
|
+
const clear = useCallback2(() => {
|
|
57428
58606
|
setCompletion("");
|
|
57429
58607
|
}, []);
|
|
57430
58608
|
return {
|
|
@@ -57439,22 +58617,22 @@ function LLMLoading({ children, className }) {
|
|
|
57439
58617
|
if (!isLoading)
|
|
57440
58618
|
return null;
|
|
57441
58619
|
if (children) {
|
|
57442
|
-
return /* @__PURE__ */
|
|
58620
|
+
return /* @__PURE__ */ jsxDEV3("div", {
|
|
57443
58621
|
className,
|
|
57444
58622
|
children
|
|
57445
58623
|
}, undefined, false, undefined, this);
|
|
57446
58624
|
}
|
|
57447
|
-
return /* @__PURE__ */
|
|
58625
|
+
return /* @__PURE__ */ jsxDEV3("div", {
|
|
57448
58626
|
className,
|
|
57449
58627
|
children: [
|
|
57450
|
-
/* @__PURE__ */
|
|
58628
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
57451
58629
|
children: [
|
|
57452
58630
|
"Loading model... ",
|
|
57453
58631
|
loadProgress?.progress ?? 0,
|
|
57454
58632
|
"%"
|
|
57455
58633
|
]
|
|
57456
58634
|
}, undefined, true, undefined, this),
|
|
57457
|
-
/* @__PURE__ */
|
|
58635
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
57458
58636
|
children: loadProgress?.status
|
|
57459
58637
|
}, undefined, false, undefined, this)
|
|
57460
58638
|
]
|
|
@@ -57463,11 +58641,11 @@ function LLMLoading({ children, className }) {
|
|
|
57463
58641
|
function LLMReady({ children, fallback = null }) {
|
|
57464
58642
|
const { isReady, isLoading } = useLLM();
|
|
57465
58643
|
if (isLoading || !isReady) {
|
|
57466
|
-
return /* @__PURE__ */
|
|
58644
|
+
return /* @__PURE__ */ jsxDEV3(Fragment3, {
|
|
57467
58645
|
children: fallback
|
|
57468
58646
|
}, undefined, false, undefined, this);
|
|
57469
58647
|
}
|
|
57470
|
-
return /* @__PURE__ */
|
|
58648
|
+
return /* @__PURE__ */ jsxDEV3(Fragment3, {
|
|
57471
58649
|
children
|
|
57472
58650
|
}, undefined, false, undefined, this);
|
|
57473
58651
|
}
|
|
@@ -57497,5 +58675,7 @@ export {
|
|
|
57497
58675
|
LLMProvider,
|
|
57498
58676
|
LLMLoading,
|
|
57499
58677
|
DEFAULT_WEBLLM_MODEL,
|
|
57500
|
-
DEFAULT_TRANSFORMERS_MODEL
|
|
58678
|
+
DEFAULT_TRANSFORMERS_MODEL,
|
|
58679
|
+
ChatInput,
|
|
58680
|
+
Chat2 as Chat
|
|
57501
58681
|
};
|