@pactor-app/chat 1.2.0 → 1.7.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/index.cjs +145 -96
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +128 -79
- package/package.json +6 -6
- package/styles.css +61 -35
package/dist/index.cjs
CHANGED
|
@@ -500,6 +500,16 @@ function pairToolTraces(parts) {
|
|
|
500
500
|
}
|
|
501
501
|
|
|
502
502
|
// src/transport.ts
|
|
503
|
+
function markCancelled(store, messageId) {
|
|
504
|
+
const message = store.getMessage(messageId);
|
|
505
|
+
if (!message) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
const parts = message.parts.map(
|
|
509
|
+
(part) => "status" in part && (part.status === "streaming" || part.status === "pending") ? { ...part, status: "ready" } : part
|
|
510
|
+
);
|
|
511
|
+
store.updateMessage(messageId, { status: "cancelled", parts });
|
|
512
|
+
}
|
|
503
513
|
async function runChatTurn(store, transport, input, options = {}) {
|
|
504
514
|
const userMessageId = options.userMessageId ?? createChatId("msg");
|
|
505
515
|
const assistantMessageId = options.assistantMessageId ?? createChatId("msg");
|
|
@@ -522,15 +532,15 @@ async function runChatTurn(store, transport, input, options = {}) {
|
|
|
522
532
|
createdAt: Date.now()
|
|
523
533
|
});
|
|
524
534
|
try {
|
|
525
|
-
for await (const event of transport.send(input)) {
|
|
535
|
+
for await (const event of transport.send(input, { signal: options.signal })) {
|
|
526
536
|
if (options.signal?.aborted) {
|
|
527
|
-
store
|
|
537
|
+
markCancelled(store, assistantMessageId);
|
|
528
538
|
return { userMessageId, assistantMessageId };
|
|
529
539
|
}
|
|
530
540
|
applyChatEvent(store, { ...event, messageId: assistantMessageId });
|
|
531
541
|
}
|
|
532
542
|
if (options.signal?.aborted) {
|
|
533
|
-
store
|
|
543
|
+
markCancelled(store, assistantMessageId);
|
|
534
544
|
return { userMessageId, assistantMessageId };
|
|
535
545
|
}
|
|
536
546
|
const message = store.getMessage(assistantMessageId);
|
|
@@ -858,7 +868,7 @@ function useChatAutoScroll({
|
|
|
858
868
|
|
|
859
869
|
// src/chat-composition.tsx
|
|
860
870
|
var import_runtime5 = require("@pactor-app/runtime");
|
|
861
|
-
var
|
|
871
|
+
var import_react17 = require("react");
|
|
862
872
|
|
|
863
873
|
// src/hooks/use-chat-model.ts
|
|
864
874
|
var import_react3 = require("react");
|
|
@@ -916,13 +926,50 @@ var import_components4 = require("@pactor-app/ui/components");
|
|
|
916
926
|
var import_core3 = require("@pactor-app/core");
|
|
917
927
|
var import_markdown2 = require("@pactor-app/markdown");
|
|
918
928
|
var import_runtime4 = require("@pactor-app/runtime");
|
|
919
|
-
var
|
|
929
|
+
var import_react6 = require("react");
|
|
920
930
|
|
|
921
931
|
// src/view/PartRenderer.tsx
|
|
922
932
|
var import_components2 = require("@pactor-app/ui/components");
|
|
923
933
|
var import_markdown = require("@pactor-app/markdown");
|
|
924
934
|
var import_runtime3 = require("@pactor-app/runtime");
|
|
925
935
|
|
|
936
|
+
// src/hooks/use-throttled-value.ts
|
|
937
|
+
var import_react4 = require("react");
|
|
938
|
+
function useThrottledValue(value, intervalMs, enabled) {
|
|
939
|
+
const [shown, setShown] = (0, import_react4.useState)(value);
|
|
940
|
+
const lastUpdateRef = (0, import_react4.useRef)(0);
|
|
941
|
+
const timerRef = (0, import_react4.useRef)(void 0);
|
|
942
|
+
(0, import_react4.useEffect)(() => {
|
|
943
|
+
if (!enabled) {
|
|
944
|
+
if (timerRef.current) {
|
|
945
|
+
clearTimeout(timerRef.current);
|
|
946
|
+
timerRef.current = void 0;
|
|
947
|
+
}
|
|
948
|
+
setShown(value);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
const now = Date.now();
|
|
952
|
+
const elapsed = now - lastUpdateRef.current;
|
|
953
|
+
if (elapsed >= intervalMs) {
|
|
954
|
+
lastUpdateRef.current = now;
|
|
955
|
+
setShown(value);
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
timerRef.current = setTimeout(() => {
|
|
959
|
+
lastUpdateRef.current = Date.now();
|
|
960
|
+
setShown(value);
|
|
961
|
+
timerRef.current = void 0;
|
|
962
|
+
}, intervalMs - elapsed);
|
|
963
|
+
return () => {
|
|
964
|
+
if (timerRef.current) {
|
|
965
|
+
clearTimeout(timerRef.current);
|
|
966
|
+
timerRef.current = void 0;
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
}, [value, intervalMs, enabled]);
|
|
970
|
+
return enabled ? shown : value;
|
|
971
|
+
}
|
|
972
|
+
|
|
926
973
|
// src/view/chrome/artifact-card.tsx
|
|
927
974
|
function buildArtifactCardFragment(artifact) {
|
|
928
975
|
return {
|
|
@@ -977,7 +1024,7 @@ function buildArtifactCardFragment(artifact) {
|
|
|
977
1024
|
|
|
978
1025
|
// src/view/chrome/ChromeSlot.tsx
|
|
979
1026
|
var import_runtime2 = require("@pactor-app/runtime");
|
|
980
|
-
var
|
|
1027
|
+
var import_react5 = require("react");
|
|
981
1028
|
|
|
982
1029
|
// src/view/chrome/actions.ts
|
|
983
1030
|
var handlers = {};
|
|
@@ -1111,7 +1158,7 @@ function ChromeSlotInner({
|
|
|
1111
1158
|
const rendered = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
|
|
1112
1159
|
return wrap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: wrap(rendered) }) : rendered;
|
|
1113
1160
|
}
|
|
1114
|
-
var ChromeSlotGuard = class extends
|
|
1161
|
+
var ChromeSlotGuard = class extends import_react5.Component {
|
|
1115
1162
|
constructor() {
|
|
1116
1163
|
super(...arguments);
|
|
1117
1164
|
this.state = { failed: false };
|
|
@@ -1169,7 +1216,8 @@ function SmoothText({ content, streaming }) {
|
|
|
1169
1216
|
}
|
|
1170
1217
|
function SmoothMarkdown({ content, streaming }) {
|
|
1171
1218
|
const shown = useSmoothStreamText(content, streaming);
|
|
1172
|
-
|
|
1219
|
+
const throttled = useThrottledValue(shown, 100, streaming);
|
|
1220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_markdown.MarkdownRenderer, { content: throttled });
|
|
1173
1221
|
}
|
|
1174
1222
|
function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact }) {
|
|
1175
1223
|
switch (part.type) {
|
|
@@ -1310,7 +1358,7 @@ function buildPanelHeaderFragment(props) {
|
|
|
1310
1358
|
// src/view/ArtifactPanel.tsx
|
|
1311
1359
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1312
1360
|
function useArtifactRuntime(safeRegistry, user) {
|
|
1313
|
-
return (0,
|
|
1361
|
+
return (0, import_react6.useMemo)(() => {
|
|
1314
1362
|
if (!safeRegistry) {
|
|
1315
1363
|
return void 0;
|
|
1316
1364
|
}
|
|
@@ -1322,7 +1370,7 @@ function useArtifactRuntime(safeRegistry, user) {
|
|
|
1322
1370
|
return createChatRuntime({ safeRegistry: components, user });
|
|
1323
1371
|
}, [safeRegistry, user]);
|
|
1324
1372
|
}
|
|
1325
|
-
var ArtifactDslGuard = class extends
|
|
1373
|
+
var ArtifactDslGuard = class extends import_react6.Component {
|
|
1326
1374
|
constructor() {
|
|
1327
1375
|
super(...arguments);
|
|
1328
1376
|
this.state = { failed: false };
|
|
@@ -1381,13 +1429,13 @@ function ArtifactPanel({
|
|
|
1381
1429
|
className
|
|
1382
1430
|
}) {
|
|
1383
1431
|
const runtime = useArtifactRuntime(safeRegistry, user);
|
|
1384
|
-
const closeRef = (0,
|
|
1432
|
+
const closeRef = (0, import_react6.useRef)(onClose);
|
|
1385
1433
|
closeRef.current = onClose;
|
|
1386
|
-
(0,
|
|
1434
|
+
(0, import_react6.useEffect)(() => {
|
|
1387
1435
|
setChatChromeHandlers({ panelClose: () => closeRef.current?.() });
|
|
1388
1436
|
}, []);
|
|
1389
|
-
const panelRef = (0,
|
|
1390
|
-
const [width, setWidth] = (0,
|
|
1437
|
+
const panelRef = (0, import_react6.useRef)(null);
|
|
1438
|
+
const [width, setWidth] = (0, import_react6.useState)(null);
|
|
1391
1439
|
const handleResizeStart = (event) => {
|
|
1392
1440
|
event.preventDefault();
|
|
1393
1441
|
const panel = panelRef.current;
|
|
@@ -1464,14 +1512,14 @@ function ArtifactPanel({
|
|
|
1464
1512
|
// src/view/ChatView.tsx
|
|
1465
1513
|
var import_components10 = require("@pactor-app/ui/components");
|
|
1466
1514
|
var import_core4 = require("@pactor-app/core");
|
|
1467
|
-
var
|
|
1515
|
+
var import_react15 = require("react");
|
|
1468
1516
|
|
|
1469
1517
|
// src/view/Composer.tsx
|
|
1470
1518
|
var import_components7 = require("@pactor-app/ui/components");
|
|
1471
|
-
var
|
|
1519
|
+
var import_react11 = require("react");
|
|
1472
1520
|
|
|
1473
1521
|
// src/view/AnchoredPopover.tsx
|
|
1474
|
-
var
|
|
1522
|
+
var import_react7 = require("react");
|
|
1475
1523
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1476
1524
|
function AnchoredPopover({
|
|
1477
1525
|
anchorRect,
|
|
@@ -1481,9 +1529,9 @@ function AnchoredPopover({
|
|
|
1481
1529
|
role = "dialog",
|
|
1482
1530
|
sideOffset = 8
|
|
1483
1531
|
}) {
|
|
1484
|
-
const ref = (0,
|
|
1485
|
-
const [position, setPosition] = (0,
|
|
1486
|
-
(0,
|
|
1532
|
+
const ref = (0, import_react7.useRef)(null);
|
|
1533
|
+
const [position, setPosition] = (0, import_react7.useState)(null);
|
|
1534
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
1487
1535
|
const element = ref.current;
|
|
1488
1536
|
if (!element) return;
|
|
1489
1537
|
const height = element.offsetHeight;
|
|
@@ -1501,7 +1549,7 @@ function AnchoredPopover({
|
|
|
1501
1549
|
}
|
|
1502
1550
|
);
|
|
1503
1551
|
}, [anchorRect, sideOffset]);
|
|
1504
|
-
(0,
|
|
1552
|
+
(0, import_react7.useEffect)(() => {
|
|
1505
1553
|
const onKeyDown = (event) => {
|
|
1506
1554
|
if (event.key !== "Escape") return;
|
|
1507
1555
|
const element = ref.current;
|
|
@@ -1549,7 +1597,7 @@ function AnchoredPopover({
|
|
|
1549
1597
|
|
|
1550
1598
|
// src/view/ModelChip.tsx
|
|
1551
1599
|
var import_components5 = require("@pactor-app/ui/components");
|
|
1552
|
-
var
|
|
1600
|
+
var import_react8 = require("react");
|
|
1553
1601
|
|
|
1554
1602
|
// src/view/chrome/model-select.tsx
|
|
1555
1603
|
function buildModelSelectFragment(props) {
|
|
@@ -1581,8 +1629,8 @@ function ModelChip({
|
|
|
1581
1629
|
model,
|
|
1582
1630
|
onModelChange
|
|
1583
1631
|
}) {
|
|
1584
|
-
const chipRef = (0,
|
|
1585
|
-
const [anchor, setAnchor] = (0,
|
|
1632
|
+
const chipRef = (0, import_react8.useRef)(null);
|
|
1633
|
+
const [anchor, setAnchor] = (0, import_react8.useState)(null);
|
|
1586
1634
|
const currentOption = models.find((option) => option.value === model) ?? models[0];
|
|
1587
1635
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1588
1636
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
@@ -1633,9 +1681,9 @@ function ModelSelect({
|
|
|
1633
1681
|
model,
|
|
1634
1682
|
onModelChange
|
|
1635
1683
|
}) {
|
|
1636
|
-
const changeRef = (0,
|
|
1684
|
+
const changeRef = (0, import_react8.useRef)(onModelChange);
|
|
1637
1685
|
changeRef.current = onModelChange;
|
|
1638
|
-
(0,
|
|
1686
|
+
(0, import_react8.useEffect)(() => {
|
|
1639
1687
|
setChatChromeHandlers({
|
|
1640
1688
|
modelChange: (value) => changeRef.current?.(value)
|
|
1641
1689
|
});
|
|
@@ -1651,13 +1699,13 @@ function ModelSelect({
|
|
|
1651
1699
|
|
|
1652
1700
|
// src/view/chrome/composer.tsx
|
|
1653
1701
|
var import_components6 = require("@pactor-app/ui/components");
|
|
1654
|
-
var
|
|
1702
|
+
var import_react9 = require("react");
|
|
1655
1703
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1656
|
-
var ComposerBridgeContext = (0,
|
|
1704
|
+
var ComposerBridgeContext = (0, import_react9.createContext)(
|
|
1657
1705
|
null
|
|
1658
1706
|
);
|
|
1659
1707
|
function useComposerBridge() {
|
|
1660
|
-
const bridge = (0,
|
|
1708
|
+
const bridge = (0, import_react9.useContext)(ComposerBridgeContext);
|
|
1661
1709
|
if (!bridge) {
|
|
1662
1710
|
throw new Error(
|
|
1663
1711
|
"[@pactor-app/chat] ChatComposer* \u5185\u90E8\u7EC4\u4EF6\u4EC5\u53EF\u5728 Composer chrome \u7247\u6BB5\u5185\u6E32\u67D3"
|
|
@@ -1863,7 +1911,7 @@ function buildComposerFragment(props) {
|
|
|
1863
1911
|
}
|
|
1864
1912
|
|
|
1865
1913
|
// src/view/context-sources.tsx
|
|
1866
|
-
var
|
|
1914
|
+
var import_react10 = require("react");
|
|
1867
1915
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1868
1916
|
function sourceCacheKey(source) {
|
|
1869
1917
|
return `${source.service ?? ""}:${JSON.stringify(source.params ?? {})}`;
|
|
@@ -1899,8 +1947,8 @@ function ContextSourceList({
|
|
|
1899
1947
|
cache,
|
|
1900
1948
|
onSelect
|
|
1901
1949
|
}) {
|
|
1902
|
-
const [resolutions, setResolutions] = (0,
|
|
1903
|
-
(0,
|
|
1950
|
+
const [resolutions, setResolutions] = (0, import_react10.useState)([]);
|
|
1951
|
+
(0, import_react10.useEffect)(() => {
|
|
1904
1952
|
let cancelled = false;
|
|
1905
1953
|
const initial = sources.map(
|
|
1906
1954
|
(source) => source.items ? { status: "ready", items: source.items } : { status: "loading" }
|
|
@@ -2000,26 +2048,26 @@ function Composer({
|
|
|
2000
2048
|
composerFooter,
|
|
2001
2049
|
hideToolbar = false
|
|
2002
2050
|
}) {
|
|
2003
|
-
const [text, setText] = (0,
|
|
2004
|
-
const [dragOver, setDragOver] = (0,
|
|
2005
|
-
const inputRef = (0,
|
|
2006
|
-
const fileInputRef = (0,
|
|
2007
|
-
const plusButtonRef = (0,
|
|
2008
|
-
const composingRef = (0,
|
|
2051
|
+
const [text, setText] = (0, import_react11.useState)("");
|
|
2052
|
+
const [dragOver, setDragOver] = (0, import_react11.useState)(false);
|
|
2053
|
+
const inputRef = (0, import_react11.useRef)(null);
|
|
2054
|
+
const fileInputRef = (0, import_react11.useRef)(null);
|
|
2055
|
+
const plusButtonRef = (0, import_react11.useRef)(null);
|
|
2056
|
+
const composingRef = (0, import_react11.useRef)(false);
|
|
2009
2057
|
const modelChipEnabled = models !== void 0 && models.length > 0;
|
|
2010
|
-
const mentionSources = (0,
|
|
2058
|
+
const mentionSources = (0, import_react11.useMemo)(
|
|
2011
2059
|
() => contextSources?.filter((source) => source.trigger === "@") ?? [],
|
|
2012
2060
|
[contextSources]
|
|
2013
2061
|
);
|
|
2014
|
-
const plusSources = (0,
|
|
2062
|
+
const plusSources = (0, import_react11.useMemo)(
|
|
2015
2063
|
() => contextSources?.filter((source) => source.trigger === "+") ?? [],
|
|
2016
2064
|
[contextSources]
|
|
2017
2065
|
);
|
|
2018
2066
|
const builtinMentionEnabled = onMentionTrigger === void 0 && mentionSources.length > 0;
|
|
2019
2067
|
const builtinPlusEnabled = onPlusMenu === void 0 && plusSources.length > 0;
|
|
2020
|
-
const [mentionState, setMentionState] = (0,
|
|
2021
|
-
const [plusAnchor, setPlusAnchor] = (0,
|
|
2022
|
-
const sourceCacheRef = (0,
|
|
2068
|
+
const [mentionState, setMentionState] = (0, import_react11.useState)(null);
|
|
2069
|
+
const [plusAnchor, setPlusAnchor] = (0, import_react11.useState)(null);
|
|
2070
|
+
const sourceCacheRef = (0, import_react11.useRef)(null);
|
|
2023
2071
|
if (sourceCacheRef.current === null) {
|
|
2024
2072
|
sourceCacheRef.current = /* @__PURE__ */ new Map();
|
|
2025
2073
|
}
|
|
@@ -2038,7 +2086,7 @@ function Composer({
|
|
|
2038
2086
|
setMentionState(null);
|
|
2039
2087
|
setPlusAnchor(null);
|
|
2040
2088
|
};
|
|
2041
|
-
(0,
|
|
2089
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2042
2090
|
const input = inputRef.current;
|
|
2043
2091
|
if (input) {
|
|
2044
2092
|
input.style.height = "auto";
|
|
@@ -2053,9 +2101,9 @@ function Composer({
|
|
|
2053
2101
|
onSend?.(value);
|
|
2054
2102
|
setText("");
|
|
2055
2103
|
};
|
|
2056
|
-
const sendRef = (0,
|
|
2104
|
+
const sendRef = (0, import_react11.useRef)(send);
|
|
2057
2105
|
sendRef.current = send;
|
|
2058
|
-
(0,
|
|
2106
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2059
2107
|
setChatChromeHandlers({ composerSubmit: () => sendRef.current() });
|
|
2060
2108
|
}, []);
|
|
2061
2109
|
const syncText = (value, caret, rect) => {
|
|
@@ -2472,15 +2520,15 @@ function EmptyState({
|
|
|
2472
2520
|
}
|
|
2473
2521
|
|
|
2474
2522
|
// src/view/MessageBubble.tsx
|
|
2475
|
-
var
|
|
2523
|
+
var import_react14 = require("react");
|
|
2476
2524
|
|
|
2477
2525
|
// src/view/ActivityTrace.tsx
|
|
2478
2526
|
var import_components8 = require("@pactor-app/ui/components");
|
|
2479
2527
|
var import_markdown3 = require("@pactor-app/markdown");
|
|
2480
|
-
var
|
|
2528
|
+
var import_react12 = require("react");
|
|
2481
2529
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2482
2530
|
function usePinnedCollapse(autoOpen) {
|
|
2483
|
-
const [state, setState] = (0,
|
|
2531
|
+
const [state, setState] = (0, import_react12.useState)("auto");
|
|
2484
2532
|
const open = state === "auto" ? autoOpen : state === "pinned-open";
|
|
2485
2533
|
const toggle = () => {
|
|
2486
2534
|
setState(open ? "pinned-closed" : "pinned-open");
|
|
@@ -2506,8 +2554,8 @@ function statusText(message, mode, toolCount) {
|
|
|
2506
2554
|
}
|
|
2507
2555
|
function useElapsedSeconds(startedAt, active) {
|
|
2508
2556
|
const compute = () => Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
|
|
2509
|
-
const [elapsed, setElapsed] = (0,
|
|
2510
|
-
(0,
|
|
2557
|
+
const [elapsed, setElapsed] = (0, import_react12.useState)(compute);
|
|
2558
|
+
(0, import_react12.useEffect)(() => {
|
|
2511
2559
|
if (!active) {
|
|
2512
2560
|
setElapsed(compute());
|
|
2513
2561
|
return;
|
|
@@ -2558,7 +2606,7 @@ function formatDetail(value) {
|
|
|
2558
2606
|
}
|
|
2559
2607
|
}
|
|
2560
2608
|
function TraceRow({ entry }) {
|
|
2561
|
-
const [open, setOpen] = (0,
|
|
2609
|
+
const [open, setOpen] = (0, import_react12.useState)(false);
|
|
2562
2610
|
const summary = summarizeArgs(entry.args);
|
|
2563
2611
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2564
2612
|
"div",
|
|
@@ -2595,6 +2643,7 @@ function ThinkingCard({
|
|
|
2595
2643
|
answerPhase
|
|
2596
2644
|
}) {
|
|
2597
2645
|
const partStreaming = part.status === "streaming";
|
|
2646
|
+
const shown = useThrottledValue(part.content, 120, partStreaming);
|
|
2598
2647
|
const { open, toggle } = usePinnedCollapse(partStreaming && !answerPhase);
|
|
2599
2648
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2600
2649
|
"div",
|
|
@@ -2617,7 +2666,7 @@ function ThinkingCard({
|
|
|
2617
2666
|
]
|
|
2618
2667
|
}
|
|
2619
2668
|
),
|
|
2620
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-thinking__body", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_markdown3.MarkdownRenderer, { content: part.content }) })
|
|
2669
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-thinking__body", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-thinking__text", children: shown }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_markdown3.MarkdownRenderer, { content: part.content }) })
|
|
2621
2670
|
]
|
|
2622
2671
|
}
|
|
2623
2672
|
);
|
|
@@ -2631,7 +2680,7 @@ function ActivityTrace({ message }) {
|
|
|
2631
2680
|
);
|
|
2632
2681
|
const answerPhase = mode === "responding" || !streaming;
|
|
2633
2682
|
const { open, toggle } = usePinnedCollapse(!answerPhase);
|
|
2634
|
-
const mountTimeRef = (0,
|
|
2683
|
+
const mountTimeRef = (0, import_react12.useRef)(0);
|
|
2635
2684
|
if (mountTimeRef.current === 0) {
|
|
2636
2685
|
mountTimeRef.current = Date.now();
|
|
2637
2686
|
}
|
|
@@ -2679,7 +2728,7 @@ function ActivityTrace({ message }) {
|
|
|
2679
2728
|
|
|
2680
2729
|
// src/view/MessageActions.tsx
|
|
2681
2730
|
var import_components9 = require("@pactor-app/ui/components");
|
|
2682
|
-
var
|
|
2731
|
+
var import_react13 = require("react");
|
|
2683
2732
|
|
|
2684
2733
|
// src/view/chrome/message-actions.tsx
|
|
2685
2734
|
function buildMessageActionsFragment(args) {
|
|
@@ -2805,13 +2854,13 @@ function MessageActions({
|
|
|
2805
2854
|
callService,
|
|
2806
2855
|
onMessageAction
|
|
2807
2856
|
}) {
|
|
2808
|
-
const [copied, setCopied] = (0,
|
|
2809
|
-
const dispatchRef = (0,
|
|
2857
|
+
const [copied, setCopied] = (0, import_react13.useState)(false);
|
|
2858
|
+
const dispatchRef = (0, import_react13.useRef)(
|
|
2810
2859
|
() => {
|
|
2811
2860
|
}
|
|
2812
2861
|
);
|
|
2813
|
-
const visibleActionsRef = (0,
|
|
2814
|
-
(0,
|
|
2862
|
+
const visibleActionsRef = (0, import_react13.useRef)([]);
|
|
2863
|
+
(0, import_react13.useEffect)(() => {
|
|
2815
2864
|
setMessageActionDispatcher(message.id, (actionId) => {
|
|
2816
2865
|
const action = visibleActionsRef.current.find((a) => a.id === actionId);
|
|
2817
2866
|
if (action) {
|
|
@@ -2925,7 +2974,7 @@ function MessageEditForm({
|
|
|
2925
2974
|
onConfirm,
|
|
2926
2975
|
onCancel
|
|
2927
2976
|
}) {
|
|
2928
|
-
const [text, setText] = (0,
|
|
2977
|
+
const [text, setText] = (0, import_react14.useState)(initialText);
|
|
2929
2978
|
const confirm = () => {
|
|
2930
2979
|
const value = text.trim();
|
|
2931
2980
|
if (!value) {
|
|
@@ -2989,7 +3038,7 @@ function MessageBubble({
|
|
|
2989
3038
|
onMessageAction,
|
|
2990
3039
|
onOpenArtifact
|
|
2991
3040
|
}) {
|
|
2992
|
-
const [editing, setEditing] = (0,
|
|
3041
|
+
const [editing, setEditing] = (0, import_react14.useState)(false);
|
|
2993
3042
|
const bubbleScope = {
|
|
2994
3043
|
conversation: scope?.conversation ?? {},
|
|
2995
3044
|
message: { id: message.id },
|
|
@@ -2997,7 +3046,7 @@ function MessageBubble({
|
|
|
2997
3046
|
};
|
|
2998
3047
|
const streaming = message.status === "streaming";
|
|
2999
3048
|
const live = message.status === "pending" || message.status === "streaming";
|
|
3000
|
-
const wasLiveRef = (0,
|
|
3049
|
+
const wasLiveRef = (0, import_react14.useRef)(live);
|
|
3001
3050
|
if (live) {
|
|
3002
3051
|
wasLiveRef.current = true;
|
|
3003
3052
|
}
|
|
@@ -3104,14 +3153,14 @@ function ChatView({
|
|
|
3104
3153
|
onMessageAction,
|
|
3105
3154
|
composerBottom
|
|
3106
3155
|
}) {
|
|
3107
|
-
const messages = (0,
|
|
3156
|
+
const messages = (0, import_react15.useSyncExternalStore)(
|
|
3108
3157
|
(listener) => store.subscribe(listener),
|
|
3109
3158
|
() => store.getMessages()
|
|
3110
3159
|
);
|
|
3111
3160
|
const isStreaming = messages.some(
|
|
3112
3161
|
(message) => message.status === "pending" || message.status === "streaming"
|
|
3113
3162
|
);
|
|
3114
|
-
const runtime = (0,
|
|
3163
|
+
const runtime = (0, import_react15.useMemo)(() => {
|
|
3115
3164
|
if (!safeRegistry) {
|
|
3116
3165
|
return void 0;
|
|
3117
3166
|
}
|
|
@@ -3128,12 +3177,12 @@ function ChatView({
|
|
|
3128
3177
|
user
|
|
3129
3178
|
});
|
|
3130
3179
|
}, [safeRegistry, capabilities, permission, confirm, user]);
|
|
3131
|
-
const scope = (0,
|
|
3180
|
+
const scope = (0, import_react15.useMemo)(
|
|
3132
3181
|
() => ({ conversation: { id: conversationId }, params }),
|
|
3133
3182
|
[conversationId, params]
|
|
3134
3183
|
);
|
|
3135
|
-
const notifiedArtifactsRef = (0,
|
|
3136
|
-
(0,
|
|
3184
|
+
const notifiedArtifactsRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
|
|
3185
|
+
(0, import_react15.useEffect)(() => {
|
|
3137
3186
|
if (!onArtifact) {
|
|
3138
3187
|
return;
|
|
3139
3188
|
}
|
|
@@ -3152,7 +3201,7 @@ function ChatView({
|
|
|
3152
3201
|
});
|
|
3153
3202
|
}
|
|
3154
3203
|
}, [messages, onArtifact]);
|
|
3155
|
-
const abortRef = (0,
|
|
3204
|
+
const abortRef = (0, import_react15.useRef)(null);
|
|
3156
3205
|
const { containerRef, isFollowing, scrollToBottom } = useChatAutoScroll({
|
|
3157
3206
|
messageCount: messages.length,
|
|
3158
3207
|
lastContentLength: lastContentLength(messages),
|
|
@@ -3163,7 +3212,7 @@ function ChatView({
|
|
|
3163
3212
|
model,
|
|
3164
3213
|
onModelChange
|
|
3165
3214
|
});
|
|
3166
|
-
const [contextChips, setContextChips] = (0,
|
|
3215
|
+
const [contextChips, setContextChips] = (0, import_react15.useState)([]);
|
|
3167
3216
|
const handleContextChipsChange = (chips) => {
|
|
3168
3217
|
setContextChips(chips);
|
|
3169
3218
|
onContextsChange?.(chips);
|
|
@@ -3195,11 +3244,11 @@ function ChatView({
|
|
|
3195
3244
|
abortRef.current?.abort();
|
|
3196
3245
|
abortRef.current = null;
|
|
3197
3246
|
};
|
|
3198
|
-
const handleSendRef = (0,
|
|
3247
|
+
const handleSendRef = (0, import_react15.useRef)(handleSend);
|
|
3199
3248
|
handleSendRef.current = handleSend;
|
|
3200
|
-
const onOpenArtifactRef = (0,
|
|
3249
|
+
const onOpenArtifactRef = (0, import_react15.useRef)(onOpenArtifact);
|
|
3201
3250
|
onOpenArtifactRef.current = onOpenArtifact;
|
|
3202
|
-
(0,
|
|
3251
|
+
(0, import_react15.useEffect)(() => {
|
|
3203
3252
|
setChatChromeHandlers({
|
|
3204
3253
|
sendSuggestion: (text) => handleSendRef.current(text),
|
|
3205
3254
|
openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact)
|
|
@@ -3306,7 +3355,7 @@ function ChatView({
|
|
|
3306
3355
|
|
|
3307
3356
|
// src/view/WorkspaceHeader.tsx
|
|
3308
3357
|
var import_components11 = require("@pactor-app/ui/components");
|
|
3309
|
-
var
|
|
3358
|
+
var import_react16 = require("react");
|
|
3310
3359
|
|
|
3311
3360
|
// src/export-markdown.ts
|
|
3312
3361
|
var ROLE_LABELS = {
|
|
@@ -3403,10 +3452,10 @@ function WorkspaceHeader({
|
|
|
3403
3452
|
onTitleChange
|
|
3404
3453
|
}) {
|
|
3405
3454
|
const hasActions = headerActions !== void 0 && headerActions.length > 0;
|
|
3406
|
-
const [overrideTitle, setOverrideTitle] = (0,
|
|
3407
|
-
const [editing, setEditing] = (0,
|
|
3408
|
-
const [draft, setDraft] = (0,
|
|
3409
|
-
const prevTitleRef = (0,
|
|
3455
|
+
const [overrideTitle, setOverrideTitle] = (0, import_react16.useState)(null);
|
|
3456
|
+
const [editing, setEditing] = (0, import_react16.useState)(false);
|
|
3457
|
+
const [draft, setDraft] = (0, import_react16.useState)("");
|
|
3458
|
+
const prevTitleRef = (0, import_react16.useRef)(title);
|
|
3410
3459
|
if (prevTitleRef.current !== title) {
|
|
3411
3460
|
prevTitleRef.current = title;
|
|
3412
3461
|
if (overrideTitle !== null) {
|
|
@@ -3414,7 +3463,7 @@ function WorkspaceHeader({
|
|
|
3414
3463
|
}
|
|
3415
3464
|
}
|
|
3416
3465
|
const displayTitle = overrideTitle ?? title;
|
|
3417
|
-
const [theme, setTheme] = (0,
|
|
3466
|
+
const [theme, setTheme] = (0, import_react16.useState)(readCurrentTheme);
|
|
3418
3467
|
const commitTitle = () => {
|
|
3419
3468
|
setEditing(false);
|
|
3420
3469
|
const next = draft.trim();
|
|
@@ -3441,9 +3490,9 @@ function WorkspaceHeader({
|
|
|
3441
3490
|
store.clear();
|
|
3442
3491
|
onClear?.();
|
|
3443
3492
|
};
|
|
3444
|
-
const handlersRef = (0,
|
|
3493
|
+
const handlersRef = (0, import_react16.useRef)({ handleExport, handleTheme, handleClear });
|
|
3445
3494
|
handlersRef.current = { handleExport, handleTheme, handleClear };
|
|
3446
|
-
(0,
|
|
3495
|
+
(0, import_react16.useEffect)(() => {
|
|
3447
3496
|
setChatChromeHandlers({
|
|
3448
3497
|
headerAction: (name) => {
|
|
3449
3498
|
const handlers2 = handlersRef.current;
|
|
@@ -3555,7 +3604,7 @@ function DslNodeSlotInner({ node }) {
|
|
|
3555
3604
|
const { renderChildren } = (0, import_runtime5.useRenderer)();
|
|
3556
3605
|
return renderChildren([node]);
|
|
3557
3606
|
}
|
|
3558
|
-
var DslSlotGuard = class extends
|
|
3607
|
+
var DslSlotGuard = class extends import_react17.Component {
|
|
3559
3608
|
constructor() {
|
|
3560
3609
|
super(...arguments);
|
|
3561
3610
|
this.state = { failed: false };
|
|
@@ -3576,7 +3625,7 @@ function DslNodeSlot({ node }) {
|
|
|
3576
3625
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslSlotGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslNodeSlotInner, { node }) });
|
|
3577
3626
|
}
|
|
3578
3627
|
function isDslNodeValue(value) {
|
|
3579
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && !(0,
|
|
3628
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(0, import_react17.isValidElement)(value) && typeof value.type === "string";
|
|
3580
3629
|
}
|
|
3581
3630
|
function resolveSlot(slot) {
|
|
3582
3631
|
if (slot === void 0 || slot === null) {
|
|
@@ -3627,18 +3676,18 @@ function ChatComposition({
|
|
|
3627
3676
|
onArtifact,
|
|
3628
3677
|
onOpenArtifact
|
|
3629
3678
|
}) {
|
|
3630
|
-
const storeRef = (0,
|
|
3679
|
+
const storeRef = (0, import_react17.useRef)(null);
|
|
3631
3680
|
if (storeRef.current === null) {
|
|
3632
3681
|
storeRef.current = services.store ?? services.storeFactory?.() ?? new ConversationStore();
|
|
3633
3682
|
}
|
|
3634
3683
|
const store = storeRef.current;
|
|
3635
|
-
const artifactStoreRef = (0,
|
|
3684
|
+
const artifactStoreRef = (0, import_react17.useRef)(null);
|
|
3636
3685
|
if (artifactStoreRef.current === null) {
|
|
3637
3686
|
artifactStoreRef.current = services.artifactStore ?? new ArtifactStore();
|
|
3638
3687
|
}
|
|
3639
3688
|
const artifactStore = artifactStoreRef.current;
|
|
3640
3689
|
const panelControlled = panelOpen !== void 0 || artifact !== void 0;
|
|
3641
|
-
const storeArtifact = (0,
|
|
3690
|
+
const storeArtifact = (0, import_react17.useSyncExternalStore)(
|
|
3642
3691
|
(listener) => artifactStore.subscribe(listener),
|
|
3643
3692
|
() => artifactStore.get()
|
|
3644
3693
|
);
|
|
@@ -3656,7 +3705,7 @@ function ChatComposition({
|
|
|
3656
3705
|
artifactStore.open(next);
|
|
3657
3706
|
}
|
|
3658
3707
|
};
|
|
3659
|
-
const [attachments, setAttachments] = (0,
|
|
3708
|
+
const [attachments, setAttachments] = (0, import_react17.useState)([]);
|
|
3660
3709
|
const handleAttachFiles = services.onAttachFiles ? (files) => {
|
|
3661
3710
|
void Promise.resolve(services.onAttachFiles(files)).then(
|
|
3662
3711
|
(created) => {
|
|
@@ -3796,9 +3845,9 @@ function ChatComposition({
|
|
|
3796
3845
|
}
|
|
3797
3846
|
|
|
3798
3847
|
// src/chat-services.tsx
|
|
3799
|
-
var
|
|
3848
|
+
var import_react18 = require("react");
|
|
3800
3849
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3801
|
-
var ChatServicesContext = (0,
|
|
3850
|
+
var ChatServicesContext = (0, import_react18.createContext)(null);
|
|
3802
3851
|
function ChatServicesProvider({
|
|
3803
3852
|
value,
|
|
3804
3853
|
children
|
|
@@ -3806,7 +3855,7 @@ function ChatServicesProvider({
|
|
|
3806
3855
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChatServicesContext.Provider, { value, children });
|
|
3807
3856
|
}
|
|
3808
3857
|
function useChatServices() {
|
|
3809
|
-
return (0,
|
|
3858
|
+
return (0, import_react18.useContext)(ChatServicesContext);
|
|
3810
3859
|
}
|
|
3811
3860
|
|
|
3812
3861
|
// src/chat-workspace.tsx
|
|
@@ -3893,7 +3942,7 @@ function createChatWorkspace(services) {
|
|
|
3893
3942
|
|
|
3894
3943
|
// src/view/Chat.tsx
|
|
3895
3944
|
var import_components12 = require("@pactor-app/ui/components");
|
|
3896
|
-
var
|
|
3945
|
+
var import_react19 = require("react");
|
|
3897
3946
|
|
|
3898
3947
|
// src/view/chrome/menu.tsx
|
|
3899
3948
|
function buildSidebarMenuFragment(props) {
|
|
@@ -3981,13 +4030,13 @@ function ChatSidebarMenu({
|
|
|
3981
4030
|
onMenuSelect
|
|
3982
4031
|
}) {
|
|
3983
4032
|
const drawer = useSidebarDrawer();
|
|
3984
|
-
const menuRef = (0,
|
|
4033
|
+
const menuRef = (0, import_react19.useRef)(menu);
|
|
3985
4034
|
menuRef.current = menu;
|
|
3986
|
-
const selectRef = (0,
|
|
4035
|
+
const selectRef = (0, import_react19.useRef)(onMenuSelect);
|
|
3987
4036
|
selectRef.current = onMenuSelect;
|
|
3988
|
-
const drawerRef = (0,
|
|
4037
|
+
const drawerRef = (0, import_react19.useRef)(drawer);
|
|
3989
4038
|
drawerRef.current = drawer;
|
|
3990
|
-
(0,
|
|
4039
|
+
(0, import_react19.useEffect)(() => {
|
|
3991
4040
|
setChatChromeHandlers({
|
|
3992
4041
|
menuSelect: (key) => {
|
|
3993
4042
|
const item = menuRef.current.find((entry) => entry.key === key);
|
|
@@ -4028,7 +4077,7 @@ function ChatSidebarMenu({
|
|
|
4028
4077
|
]
|
|
4029
4078
|
}
|
|
4030
4079
|
);
|
|
4031
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4080
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react19.Fragment, { children: [
|
|
4032
4081
|
groupLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
|
|
4033
4082
|
collapsed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components12.RailTooltip, { label: item.label, children: button }) : button
|
|
4034
4083
|
] }, item.key);
|
|
@@ -4085,7 +4134,7 @@ function Chat({
|
|
|
4085
4134
|
onMenuSelect
|
|
4086
4135
|
}) {
|
|
4087
4136
|
const services = useChatServices();
|
|
4088
|
-
(0,
|
|
4137
|
+
(0, import_react19.useEffect)(() => {
|
|
4089
4138
|
if (!services) {
|
|
4090
4139
|
console.warn(
|
|
4091
4140
|
"[@pactor-app/chat] Chat \u672A\u68C0\u6D4B\u5230 ChatServicesProvider\uFF1A\u8BF7\u5728\u5E94\u7528\u6839\u90E8\u4EE5 <ChatServicesProvider> \u6CE8\u5165 transport \u7B49\u670D\u52A1"
|
package/dist/index.d.cts
CHANGED
|
@@ -410,9 +410,13 @@ interface ChatInput {
|
|
|
410
410
|
*/
|
|
411
411
|
contexts?: ChatContextItem[];
|
|
412
412
|
}
|
|
413
|
+
/** 传输层发送选项 */
|
|
414
|
+
interface ChatTransportSendOptions {
|
|
415
|
+
signal?: AbortSignal;
|
|
416
|
+
}
|
|
413
417
|
/** Chat 传输层:发送输入,返回流式事件 */
|
|
414
418
|
interface ChatTransport {
|
|
415
|
-
send(input: ChatInput): AsyncIterable<ChatEvent>;
|
|
419
|
+
send(input: ChatInput, options?: ChatTransportSendOptions): AsyncIterable<ChatEvent>;
|
|
416
420
|
}
|
|
417
421
|
/** runChatTurn 的可选定制(id 生成等,测试可注入确定性 id) */
|
|
418
422
|
interface RunChatTurnOptions {
|