@floegence/floe-webapp-core 0.27.3 → 0.27.5
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.
|
@@ -6,6 +6,7 @@ export interface ChatContextValue {
|
|
|
6
6
|
isLoadingHistory: Accessor<boolean>;
|
|
7
7
|
hasMoreHistory: Accessor<boolean>;
|
|
8
8
|
streamingMessageId: Accessor<string | null>;
|
|
9
|
+
isPreparing: Accessor<boolean>;
|
|
9
10
|
isWorking: Accessor<boolean>;
|
|
10
11
|
config: Accessor<ChatConfig>;
|
|
11
12
|
virtualListConfig: Accessor<VirtualListConfig>;
|
|
@@ -1,60 +1,79 @@
|
|
|
1
|
-
import { createComponent as
|
|
2
|
-
import { createMemo as
|
|
3
|
-
import { createStore as
|
|
4
|
-
import { deferNonBlocking as
|
|
5
|
-
import { DEFAULT_VIRTUAL_LIST_CONFIG as
|
|
6
|
-
const
|
|
7
|
-
function
|
|
8
|
-
const
|
|
9
|
-
if (!
|
|
1
|
+
import { createComponent as X } from "solid-js/web";
|
|
2
|
+
import { createMemo as b, createEffect as Y, on as Z, createSignal as C, useContext as $, createContext as ee, batch as E } from "solid-js";
|
|
3
|
+
import { createStore as te, reconcile as v, produce as M } from "solid-js/store";
|
|
4
|
+
import { deferNonBlocking as p } from "../../utils/defer.js";
|
|
5
|
+
import { DEFAULT_VIRTUAL_LIST_CONFIG as se } from "./types.js";
|
|
6
|
+
const F = ee();
|
|
7
|
+
function Ce() {
|
|
8
|
+
const o = $(F);
|
|
9
|
+
if (!o)
|
|
10
10
|
throw new Error("useChatContext must be used within a ChatProvider");
|
|
11
|
-
return
|
|
11
|
+
return o;
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const Me = (o) => {
|
|
14
|
+
const S = b(() => ({
|
|
15
15
|
placeholder: "Type a message...",
|
|
16
16
|
allowAttachments: !0,
|
|
17
17
|
maxAttachments: 10,
|
|
18
18
|
maxAttachmentSize: 10485760,
|
|
19
19
|
// 10MB
|
|
20
|
-
...
|
|
21
|
-
})),
|
|
22
|
-
...
|
|
23
|
-
...
|
|
24
|
-
})), [c, u] =
|
|
25
|
-
|
|
26
|
-
e && e.length > 0 && u(
|
|
20
|
+
...o.config
|
|
21
|
+
})), d = b(() => ({
|
|
22
|
+
...se,
|
|
23
|
+
...o.config?.virtualList
|
|
24
|
+
})), [c, u] = te(o.initialMessages || []), z = /* @__PURE__ */ new Map();
|
|
25
|
+
Y(Z(() => o.initialMessages, (e) => {
|
|
26
|
+
e && e.length > 0 && u(v(e));
|
|
27
27
|
}, {
|
|
28
28
|
defer: !0
|
|
29
29
|
}));
|
|
30
|
-
const [
|
|
31
|
-
|
|
30
|
+
const [A, H] = C(!1), [P, R] = C(!0), [L, x] = C(null), [B, I] = C(0);
|
|
31
|
+
let D = 0;
|
|
32
|
+
const g = /* @__PURE__ */ new Set(), h = [], f = /* @__PURE__ */ new Map(), O = (e) => {
|
|
33
|
+
if (!g.delete(e)) return;
|
|
34
|
+
const t = h.indexOf(e);
|
|
35
|
+
t >= 0 && h.splice(t, 1), I(g.size);
|
|
36
|
+
}, j = () => {
|
|
37
|
+
const e = ++D;
|
|
38
|
+
return g.add(e), h.push(e), I(g.size), e;
|
|
39
|
+
}, q = () => {
|
|
40
|
+
for (; h.length > 0; ) {
|
|
41
|
+
const e = h.shift();
|
|
42
|
+
if (e === void 0) return;
|
|
43
|
+
if (g.has(e)) {
|
|
44
|
+
g.delete(e), I(g.size);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}, U = b(() => B() > 0), N = b(() => U() || L() !== null), k = (e) => {
|
|
49
|
+
u(M((t) => {
|
|
32
50
|
t.push(e);
|
|
33
51
|
}));
|
|
34
52
|
}, l = (e, t) => {
|
|
35
|
-
u(
|
|
36
|
-
const
|
|
37
|
-
|
|
53
|
+
u(M((s) => {
|
|
54
|
+
const n = s.findIndex((a) => a.id === e);
|
|
55
|
+
n !== -1 && (s[n] = t(s[n]));
|
|
38
56
|
}));
|
|
39
|
-
},
|
|
40
|
-
u(
|
|
41
|
-
const s = t.findIndex((
|
|
57
|
+
}, W = (e) => {
|
|
58
|
+
u(M((t) => {
|
|
59
|
+
const s = t.findIndex((n) => n.id === e);
|
|
42
60
|
s !== -1 && t.splice(s, 1);
|
|
43
|
-
})),
|
|
44
|
-
},
|
|
45
|
-
u(
|
|
46
|
-
},
|
|
47
|
-
u(
|
|
61
|
+
})), f.delete(e);
|
|
62
|
+
}, _ = () => {
|
|
63
|
+
u(v([])), f.clear();
|
|
64
|
+
}, V = (e) => {
|
|
65
|
+
u(v(e));
|
|
48
66
|
};
|
|
49
|
-
let
|
|
50
|
-
const
|
|
51
|
-
const e =
|
|
52
|
-
|
|
53
|
-
e.forEach(
|
|
67
|
+
let T = [], w = null;
|
|
68
|
+
const G = () => {
|
|
69
|
+
const e = T;
|
|
70
|
+
T = [], w = null, E(() => {
|
|
71
|
+
e.forEach(Q);
|
|
54
72
|
});
|
|
55
|
-
},
|
|
73
|
+
}, Q = (e) => {
|
|
56
74
|
switch (e.type) {
|
|
57
75
|
case "message-start": {
|
|
76
|
+
q();
|
|
58
77
|
const t = {
|
|
59
78
|
id: e.messageId,
|
|
60
79
|
role: "assistant",
|
|
@@ -62,20 +81,20 @@ const ge = (r) => {
|
|
|
62
81
|
status: "streaming",
|
|
63
82
|
timestamp: Date.now()
|
|
64
83
|
};
|
|
65
|
-
|
|
84
|
+
k(t), x(e.messageId);
|
|
66
85
|
break;
|
|
67
86
|
}
|
|
68
87
|
case "block-start": {
|
|
69
88
|
l(e.messageId, (t) => ({
|
|
70
89
|
...t,
|
|
71
|
-
blocks: [...t.blocks,
|
|
90
|
+
blocks: [...t.blocks, ne(e.blockType)]
|
|
72
91
|
}));
|
|
73
92
|
break;
|
|
74
93
|
}
|
|
75
94
|
case "block-delta": {
|
|
76
95
|
l(e.messageId, (t) => {
|
|
77
|
-
const s = [...t.blocks],
|
|
78
|
-
return
|
|
96
|
+
const s = [...t.blocks], n = s[e.blockIndex];
|
|
97
|
+
return n && "content" in n && typeof n.content == "string" && (n.content += e.delta), {
|
|
79
98
|
...t,
|
|
80
99
|
blocks: s
|
|
81
100
|
};
|
|
@@ -98,7 +117,7 @@ const ge = (r) => {
|
|
|
98
117
|
l(e.messageId, (t) => ({
|
|
99
118
|
...t,
|
|
100
119
|
status: "complete"
|
|
101
|
-
})),
|
|
120
|
+
})), x(null);
|
|
102
121
|
break;
|
|
103
122
|
}
|
|
104
123
|
case "error": {
|
|
@@ -106,64 +125,72 @@ const ge = (r) => {
|
|
|
106
125
|
...t,
|
|
107
126
|
status: "error",
|
|
108
127
|
error: e.error
|
|
109
|
-
})),
|
|
128
|
+
})), x(null);
|
|
110
129
|
break;
|
|
111
130
|
}
|
|
112
131
|
}
|
|
113
|
-
},
|
|
132
|
+
}, J = {
|
|
114
133
|
messages: () => c,
|
|
115
|
-
coldMessages:
|
|
116
|
-
isLoadingHistory:
|
|
117
|
-
hasMoreHistory:
|
|
118
|
-
streamingMessageId:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
134
|
+
coldMessages: z,
|
|
135
|
+
isLoadingHistory: A,
|
|
136
|
+
hasMoreHistory: P,
|
|
137
|
+
streamingMessageId: L,
|
|
138
|
+
isPreparing: U,
|
|
139
|
+
isWorking: N,
|
|
140
|
+
config: S,
|
|
141
|
+
virtualListConfig: d,
|
|
122
142
|
sendMessage: async (e, t = []) => {
|
|
123
143
|
const s = {
|
|
124
144
|
id: crypto.randomUUID(),
|
|
125
145
|
role: "user",
|
|
126
|
-
blocks:
|
|
146
|
+
blocks: oe(e, t),
|
|
127
147
|
status: "sending",
|
|
128
148
|
timestamp: Date.now()
|
|
129
149
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
...
|
|
150
|
+
E(() => {
|
|
151
|
+
k(s), l(s.id, (i) => ({
|
|
152
|
+
...i,
|
|
133
153
|
status: "complete"
|
|
134
154
|
}));
|
|
135
155
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
156
|
+
try {
|
|
157
|
+
o.callbacks?.onWillSend?.(e, t);
|
|
158
|
+
} catch (i) {
|
|
159
|
+
console.error("onWillSend error:", i);
|
|
160
|
+
}
|
|
161
|
+
const n = o.callbacks?.onSendMessage;
|
|
162
|
+
if (!n) return;
|
|
163
|
+
const a = j(), r = e, m = [...t];
|
|
164
|
+
p(() => {
|
|
165
|
+
Promise.resolve().then(() => n(r, m, k)).catch((i) => {
|
|
166
|
+
console.error("Failed to send message:", i);
|
|
167
|
+
}).finally(() => {
|
|
168
|
+
O(a);
|
|
142
169
|
});
|
|
143
170
|
});
|
|
144
171
|
},
|
|
145
172
|
loadMoreHistory: async () => {
|
|
146
|
-
if (
|
|
147
|
-
const e =
|
|
148
|
-
e && (
|
|
173
|
+
if (A() || !P()) return;
|
|
174
|
+
const e = o.callbacks?.onLoadMore;
|
|
175
|
+
e && (H(!0), p(() => {
|
|
149
176
|
Promise.resolve(e()).then((t) => {
|
|
150
177
|
if (t.length === 0) {
|
|
151
|
-
|
|
178
|
+
R(!1);
|
|
152
179
|
return;
|
|
153
180
|
}
|
|
154
|
-
u(
|
|
181
|
+
u(M((s) => {
|
|
155
182
|
s.unshift(...t);
|
|
156
183
|
}));
|
|
157
184
|
}).catch((t) => {
|
|
158
185
|
console.error("Failed to load history:", t);
|
|
159
186
|
}).finally(() => {
|
|
160
|
-
|
|
187
|
+
H(!1);
|
|
161
188
|
});
|
|
162
189
|
}));
|
|
163
190
|
},
|
|
164
191
|
retryMessage: (e) => {
|
|
165
|
-
const t =
|
|
166
|
-
t &&
|
|
192
|
+
const t = o.callbacks?.onRetry;
|
|
193
|
+
t && p(() => {
|
|
167
194
|
try {
|
|
168
195
|
t(e);
|
|
169
196
|
} catch (s) {
|
|
@@ -171,97 +198,97 @@ const ge = (r) => {
|
|
|
171
198
|
}
|
|
172
199
|
});
|
|
173
200
|
},
|
|
174
|
-
addMessage:
|
|
201
|
+
addMessage: k,
|
|
175
202
|
updateMessage: l,
|
|
176
|
-
deleteMessage:
|
|
177
|
-
clearMessages:
|
|
178
|
-
setMessages:
|
|
203
|
+
deleteMessage: W,
|
|
204
|
+
clearMessages: _,
|
|
205
|
+
setMessages: V,
|
|
179
206
|
handleStreamEvent: (e) => {
|
|
180
|
-
|
|
207
|
+
T.push(e), w || (w = requestAnimationFrame(G));
|
|
181
208
|
},
|
|
182
209
|
uploadAttachment: async (e) => {
|
|
183
|
-
const t =
|
|
210
|
+
const t = o.callbacks?.onUploadAttachment;
|
|
184
211
|
return t ? await t(e) : URL.createObjectURL(e);
|
|
185
212
|
},
|
|
186
213
|
toggleToolCollapse: (e, t) => {
|
|
187
214
|
l(e, (s) => ({
|
|
188
215
|
...s,
|
|
189
|
-
blocks: s.blocks.map((
|
|
190
|
-
if (
|
|
191
|
-
const
|
|
216
|
+
blocks: s.blocks.map((n) => {
|
|
217
|
+
if (n.type === "tool-call" && n.toolId === t) {
|
|
218
|
+
const a = n.collapsed === void 0 ? !1 : !n.collapsed;
|
|
192
219
|
return {
|
|
193
|
-
...
|
|
194
|
-
collapsed:
|
|
220
|
+
...n,
|
|
221
|
+
collapsed: a
|
|
195
222
|
};
|
|
196
223
|
}
|
|
197
|
-
return
|
|
224
|
+
return n;
|
|
198
225
|
})
|
|
199
226
|
}));
|
|
200
227
|
},
|
|
201
228
|
approveToolCall: (e, t, s) => {
|
|
202
|
-
l(e, (
|
|
203
|
-
...
|
|
204
|
-
blocks:
|
|
205
|
-
...
|
|
229
|
+
l(e, (a) => ({
|
|
230
|
+
...a,
|
|
231
|
+
blocks: a.blocks.map((r) => r.type !== "tool-call" || r.toolId !== t || r.requiresApproval !== !0 || r.approvalState !== "required" ? r : s ? {
|
|
232
|
+
...r,
|
|
206
233
|
approvalState: "approved",
|
|
207
234
|
status: "running"
|
|
208
235
|
} : {
|
|
209
|
-
...
|
|
236
|
+
...r,
|
|
210
237
|
approvalState: "rejected",
|
|
211
238
|
status: "error",
|
|
212
|
-
error:
|
|
239
|
+
error: r.error || "Rejected by user"
|
|
213
240
|
})
|
|
214
241
|
}));
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
Promise.resolve(
|
|
218
|
-
console.error("Failed to approve tool call:",
|
|
242
|
+
const n = o.callbacks?.onToolApproval;
|
|
243
|
+
n && p(() => {
|
|
244
|
+
Promise.resolve(n(e, t, s)).catch((a) => {
|
|
245
|
+
console.error("Failed to approve tool call:", a);
|
|
219
246
|
});
|
|
220
247
|
});
|
|
221
248
|
},
|
|
222
|
-
heightCache:
|
|
249
|
+
heightCache: f,
|
|
223
250
|
setMessageHeight: (e, t) => {
|
|
224
|
-
|
|
251
|
+
f.set(e, t);
|
|
225
252
|
},
|
|
226
|
-
getMessageHeight: (e) =>
|
|
253
|
+
getMessageHeight: (e) => f.get(e) || d().defaultItemHeight,
|
|
227
254
|
toggleChecklistItem: (e, t, s) => {
|
|
228
|
-
let
|
|
229
|
-
l(e, (
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
232
|
-
const
|
|
233
|
-
...
|
|
234
|
-
checked:
|
|
235
|
-
}) :
|
|
236
|
-
|
|
237
|
-
...
|
|
238
|
-
items:
|
|
255
|
+
let n = null;
|
|
256
|
+
l(e, (r) => {
|
|
257
|
+
const m = [...r.blocks], i = m[t];
|
|
258
|
+
if (i && i.type === "checklist") {
|
|
259
|
+
const K = i.items.map((y) => y.id === s ? (n = !y.checked, {
|
|
260
|
+
...y,
|
|
261
|
+
checked: n
|
|
262
|
+
}) : y);
|
|
263
|
+
m[t] = {
|
|
264
|
+
...i,
|
|
265
|
+
items: K
|
|
239
266
|
};
|
|
240
267
|
}
|
|
241
268
|
return {
|
|
242
|
-
...
|
|
243
|
-
blocks:
|
|
269
|
+
...r,
|
|
270
|
+
blocks: m
|
|
244
271
|
};
|
|
245
272
|
});
|
|
246
|
-
const
|
|
247
|
-
!
|
|
273
|
+
const a = o.callbacks?.onChecklistChange;
|
|
274
|
+
!a || n === null || p(() => {
|
|
248
275
|
try {
|
|
249
|
-
|
|
250
|
-
} catch (
|
|
251
|
-
console.error("Failed to handle checklist change:",
|
|
276
|
+
a(e, t, s, n);
|
|
277
|
+
} catch (r) {
|
|
278
|
+
console.error("Failed to handle checklist change:", r);
|
|
252
279
|
}
|
|
253
280
|
});
|
|
254
281
|
}
|
|
255
282
|
};
|
|
256
|
-
return
|
|
257
|
-
value:
|
|
283
|
+
return X(F.Provider, {
|
|
284
|
+
value: J,
|
|
258
285
|
get children() {
|
|
259
|
-
return
|
|
286
|
+
return o.children;
|
|
260
287
|
}
|
|
261
288
|
});
|
|
262
289
|
};
|
|
263
|
-
function
|
|
264
|
-
switch (
|
|
290
|
+
function ne(o) {
|
|
291
|
+
switch (o) {
|
|
265
292
|
case "text":
|
|
266
293
|
return {
|
|
267
294
|
type: "text",
|
|
@@ -337,26 +364,26 @@ function K(r) {
|
|
|
337
364
|
};
|
|
338
365
|
}
|
|
339
366
|
}
|
|
340
|
-
function
|
|
341
|
-
const
|
|
342
|
-
for (const c of
|
|
343
|
-
c.type === "image" ?
|
|
367
|
+
function oe(o, S) {
|
|
368
|
+
const d = [];
|
|
369
|
+
for (const c of S)
|
|
370
|
+
c.type === "image" ? d.push({
|
|
344
371
|
type: "image",
|
|
345
372
|
src: c.url || c.preview || "",
|
|
346
373
|
alt: c.file.name
|
|
347
|
-
}) :
|
|
374
|
+
}) : d.push({
|
|
348
375
|
type: "file",
|
|
349
376
|
name: c.file.name,
|
|
350
377
|
size: c.file.size,
|
|
351
378
|
mimeType: c.file.type,
|
|
352
379
|
url: c.url
|
|
353
380
|
});
|
|
354
|
-
return
|
|
381
|
+
return o.trim() && d.push({
|
|
355
382
|
type: "text",
|
|
356
|
-
content:
|
|
357
|
-
}),
|
|
383
|
+
content: o.trim()
|
|
384
|
+
}), d;
|
|
358
385
|
}
|
|
359
386
|
export {
|
|
360
|
-
|
|
361
|
-
|
|
387
|
+
Me as ChatProvider,
|
|
388
|
+
Ce as useChatContext
|
|
362
389
|
};
|
|
@@ -159,6 +159,7 @@ export interface ChatConfig {
|
|
|
159
159
|
maxAttachments?: number;
|
|
160
160
|
}
|
|
161
161
|
export interface ChatCallbacks {
|
|
162
|
+
onWillSend?: (content: string, attachments: Attachment[]) => void;
|
|
162
163
|
onSendMessage?: (content: string, attachments: Attachment[], addMessage: (msg: Message) => void) => Promise<void>;
|
|
163
164
|
onLoadMore?: () => Promise<Message[]>;
|
|
164
165
|
onRetry?: (messageId: string) => void;
|