@lantos1618/better-ui 0.7.1 → 0.8.0
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/dist/components/index.js +53 -14
- package/dist/components/index.mjs +54 -15
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.mjs +1 -1
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -179,16 +179,24 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
179
179
|
const [threads, setThreads] = (0, import_react2.useState)([]);
|
|
180
180
|
const [activeThreadId, setActiveThreadId] = (0, import_react2.useState)(threadId);
|
|
181
181
|
(0, import_react2.useEffect)(() => {
|
|
182
|
-
if (persistence)
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
if (!persistence) return;
|
|
183
|
+
let cancelled = false;
|
|
184
|
+
persistence.listThreads().then((t) => {
|
|
185
|
+
if (!cancelled) setThreads(t);
|
|
186
|
+
}).catch((err) => console.warn("[better-ui] persistence error:", err));
|
|
187
|
+
return () => {
|
|
188
|
+
cancelled = true;
|
|
189
|
+
};
|
|
185
190
|
}, [persistence]);
|
|
186
191
|
(0, import_react2.useEffect)(() => {
|
|
187
|
-
if (persistence
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
+
if (!persistence || !activeThreadId) return;
|
|
193
|
+
let cancelled = false;
|
|
194
|
+
persistence.getMessages(activeThreadId).then((msgs) => {
|
|
195
|
+
if (!cancelled) setMessages(msgs);
|
|
196
|
+
}).catch((err) => console.warn("[better-ui] persistence error:", err));
|
|
197
|
+
return () => {
|
|
198
|
+
cancelled = true;
|
|
199
|
+
};
|
|
192
200
|
}, [persistence, activeThreadId, setMessages]);
|
|
193
201
|
const prevStatusRef = (0, import_react2.useRef)(status);
|
|
194
202
|
(0, import_react2.useEffect)(() => {
|
|
@@ -212,9 +220,10 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
212
220
|
}, [persistence, setMessages, toolStateStore]);
|
|
213
221
|
const switchThreadFn = (0, import_react2.useCallback)(async (id) => {
|
|
214
222
|
if (!persistence) throw new Error("Persistence not configured");
|
|
215
|
-
|
|
216
|
-
setMessages([]);
|
|
223
|
+
const msgs = await persistence.getMessages(id);
|
|
217
224
|
toolStateStore.clear();
|
|
225
|
+
setMessages(msgs);
|
|
226
|
+
setActiveThreadId(id);
|
|
218
227
|
}, [persistence, setMessages, toolStateStore]);
|
|
219
228
|
const deleteThreadFn = (0, import_react2.useCallback)(async (id) => {
|
|
220
229
|
if (!persistence) throw new Error("Persistence not configured");
|
|
@@ -237,8 +246,11 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
237
246
|
stateContext[entry.toolName] = entry.output;
|
|
238
247
|
}
|
|
239
248
|
}
|
|
240
|
-
|
|
241
|
-
|
|
249
|
+
if (Object.keys(stateContext).length > 0) {
|
|
250
|
+
dirty.clear();
|
|
251
|
+
return stateContext;
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
242
254
|
}, [toolStateStore]);
|
|
243
255
|
const executeToolDirect = (0, import_react2.useCallback)(async (toolName, toolInput, toolCallId) => {
|
|
244
256
|
const currentVersion = (versionRef.current.get(toolCallId) || 0) + 1;
|
|
@@ -420,6 +432,33 @@ var import_ai2 = require("ai");
|
|
|
420
432
|
// src/components/ToolResult.tsx
|
|
421
433
|
var import_react4 = require("react");
|
|
422
434
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
435
|
+
var ToolViewErrorBoundary = class extends import_react4.Component {
|
|
436
|
+
constructor() {
|
|
437
|
+
super(...arguments);
|
|
438
|
+
this.state = { error: null };
|
|
439
|
+
}
|
|
440
|
+
static getDerivedStateFromError(error) {
|
|
441
|
+
return { error };
|
|
442
|
+
}
|
|
443
|
+
componentDidCatch(error, info) {
|
|
444
|
+
console.error(`[better-ui] View for tool "${this.props.toolName}" threw:`, error, info);
|
|
445
|
+
}
|
|
446
|
+
render() {
|
|
447
|
+
if (this.state.error) {
|
|
448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-[var(--bui-error-muted,rgba(220,38,38,0.08))] border border-[var(--bui-error-border,rgba(153,27,27,0.5))] rounded-xl p-4", children: [
|
|
449
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
450
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "w-4 h-4 text-[var(--bui-error-fg,#f87171)] shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" }) }),
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-[var(--bui-error-fg,#f87171)] text-sm font-medium", children: [
|
|
452
|
+
this.props.toolName,
|
|
453
|
+
" view error"
|
|
454
|
+
] })
|
|
455
|
+
] }),
|
|
456
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[var(--bui-error-fg,#f87171)]/70 text-xs mt-1", children: this.state.error.message })
|
|
457
|
+
] });
|
|
458
|
+
}
|
|
459
|
+
return this.props.children;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
423
462
|
function useIsFollowup(toolStateStore, toolCallId) {
|
|
424
463
|
const subscribe = (0, import_react4.useCallback)(
|
|
425
464
|
(listener) => toolStateStore.subscribeAll(listener),
|
|
@@ -602,7 +641,7 @@ function ToolResult({
|
|
|
602
641
|
)
|
|
603
642
|
] });
|
|
604
643
|
}
|
|
605
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ToolViewErrorBoundary, { toolName, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
606
645
|
toolDef.View,
|
|
607
646
|
{
|
|
608
647
|
data: resolvedOutput,
|
|
@@ -610,7 +649,7 @@ function ToolResult({
|
|
|
610
649
|
onAction: getOnAction(toolCallId, toolName),
|
|
611
650
|
error: storeState?.error ? new Error(storeState.error) : null
|
|
612
651
|
}
|
|
613
|
-
) });
|
|
652
|
+
) }) });
|
|
614
653
|
}
|
|
615
654
|
|
|
616
655
|
// src/components/Markdown.tsx
|
|
@@ -121,16 +121,24 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
121
121
|
const [threads, setThreads] = useState([]);
|
|
122
122
|
const [activeThreadId, setActiveThreadId] = useState(threadId);
|
|
123
123
|
useEffect(() => {
|
|
124
|
-
if (persistence)
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
if (!persistence) return;
|
|
125
|
+
let cancelled = false;
|
|
126
|
+
persistence.listThreads().then((t) => {
|
|
127
|
+
if (!cancelled) setThreads(t);
|
|
128
|
+
}).catch((err) => console.warn("[better-ui] persistence error:", err));
|
|
129
|
+
return () => {
|
|
130
|
+
cancelled = true;
|
|
131
|
+
};
|
|
127
132
|
}, [persistence]);
|
|
128
133
|
useEffect(() => {
|
|
129
|
-
if (persistence
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
+
if (!persistence || !activeThreadId) return;
|
|
135
|
+
let cancelled = false;
|
|
136
|
+
persistence.getMessages(activeThreadId).then((msgs) => {
|
|
137
|
+
if (!cancelled) setMessages(msgs);
|
|
138
|
+
}).catch((err) => console.warn("[better-ui] persistence error:", err));
|
|
139
|
+
return () => {
|
|
140
|
+
cancelled = true;
|
|
141
|
+
};
|
|
134
142
|
}, [persistence, activeThreadId, setMessages]);
|
|
135
143
|
const prevStatusRef = useRef(status);
|
|
136
144
|
useEffect(() => {
|
|
@@ -154,9 +162,10 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
154
162
|
}, [persistence, setMessages, toolStateStore]);
|
|
155
163
|
const switchThreadFn = useCallback2(async (id) => {
|
|
156
164
|
if (!persistence) throw new Error("Persistence not configured");
|
|
157
|
-
|
|
158
|
-
setMessages([]);
|
|
165
|
+
const msgs = await persistence.getMessages(id);
|
|
159
166
|
toolStateStore.clear();
|
|
167
|
+
setMessages(msgs);
|
|
168
|
+
setActiveThreadId(id);
|
|
160
169
|
}, [persistence, setMessages, toolStateStore]);
|
|
161
170
|
const deleteThreadFn = useCallback2(async (id) => {
|
|
162
171
|
if (!persistence) throw new Error("Persistence not configured");
|
|
@@ -179,8 +188,11 @@ function ChatProvider({ endpoint = "/api/chat", tools, toolStateStore: externalS
|
|
|
179
188
|
stateContext[entry.toolName] = entry.output;
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
|
-
|
|
183
|
-
|
|
191
|
+
if (Object.keys(stateContext).length > 0) {
|
|
192
|
+
dirty.clear();
|
|
193
|
+
return stateContext;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
184
196
|
}, [toolStateStore]);
|
|
185
197
|
const executeToolDirect = useCallback2(async (toolName, toolInput, toolCallId) => {
|
|
186
198
|
const currentVersion = (versionRef.current.get(toolCallId) || 0) + 1;
|
|
@@ -364,8 +376,35 @@ import {
|
|
|
364
376
|
} from "ai";
|
|
365
377
|
|
|
366
378
|
// src/components/ToolResult.tsx
|
|
367
|
-
import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback3 } from "react";
|
|
379
|
+
import { Component, useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback3 } from "react";
|
|
368
380
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
381
|
+
var ToolViewErrorBoundary = class extends Component {
|
|
382
|
+
constructor() {
|
|
383
|
+
super(...arguments);
|
|
384
|
+
this.state = { error: null };
|
|
385
|
+
}
|
|
386
|
+
static getDerivedStateFromError(error) {
|
|
387
|
+
return { error };
|
|
388
|
+
}
|
|
389
|
+
componentDidCatch(error, info) {
|
|
390
|
+
console.error(`[better-ui] View for tool "${this.props.toolName}" threw:`, error, info);
|
|
391
|
+
}
|
|
392
|
+
render() {
|
|
393
|
+
if (this.state.error) {
|
|
394
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-[var(--bui-error-muted,rgba(220,38,38,0.08))] border border-[var(--bui-error-border,rgba(153,27,27,0.5))] rounded-xl p-4", children: [
|
|
395
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
396
|
+
/* @__PURE__ */ jsx2("svg", { className: "w-4 h-4 text-[var(--bui-error-fg,#f87171)] shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" }) }),
|
|
397
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[var(--bui-error-fg,#f87171)] text-sm font-medium", children: [
|
|
398
|
+
this.props.toolName,
|
|
399
|
+
" view error"
|
|
400
|
+
] })
|
|
401
|
+
] }),
|
|
402
|
+
/* @__PURE__ */ jsx2("p", { className: "text-[var(--bui-error-fg,#f87171)]/70 text-xs mt-1", children: this.state.error.message })
|
|
403
|
+
] });
|
|
404
|
+
}
|
|
405
|
+
return this.props.children;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
369
408
|
function useIsFollowup(toolStateStore, toolCallId) {
|
|
370
409
|
const subscribe = useCallback3(
|
|
371
410
|
(listener) => toolStateStore.subscribeAll(listener),
|
|
@@ -548,7 +587,7 @@ function ToolResult({
|
|
|
548
587
|
)
|
|
549
588
|
] });
|
|
550
589
|
}
|
|
551
|
-
return /* @__PURE__ */ jsx2("div", { className: className || "", children: /* @__PURE__ */ jsx2(
|
|
590
|
+
return /* @__PURE__ */ jsx2("div", { className: className || "", children: /* @__PURE__ */ jsx2(ToolViewErrorBoundary, { toolName, children: /* @__PURE__ */ jsx2(
|
|
552
591
|
toolDef.View,
|
|
553
592
|
{
|
|
554
593
|
data: resolvedOutput,
|
|
@@ -556,7 +595,7 @@ function ToolResult({
|
|
|
556
595
|
onAction: getOnAction(toolCallId, toolName),
|
|
557
596
|
error: storeState?.error ? new Error(storeState.error) : null
|
|
558
597
|
}
|
|
559
|
-
) });
|
|
598
|
+
) }) });
|
|
560
599
|
}
|
|
561
600
|
|
|
562
601
|
// src/components/Markdown.tsx
|
package/dist/mcp/index.js
CHANGED
package/dist/mcp/index.mjs
CHANGED