@pactor-app/chat 1.0.0 → 1.2.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/README.md +3 -2
- package/dist/index.cjs +1468 -592
- package/dist/index.d.cts +111 -23
- package/dist/index.d.ts +111 -23
- package/dist/index.js +1441 -596
- package/package.json +7 -8
- package/styles.css +192 -180
package/dist/index.cjs
CHANGED
|
@@ -39,14 +39,13 @@ __export(index_exports, {
|
|
|
39
39
|
ConversationStore: () => ConversationStore,
|
|
40
40
|
DEFAULT_CHAT_GREETING: () => DEFAULT_CHAT_GREETING,
|
|
41
41
|
EmptyState: () => EmptyState,
|
|
42
|
-
MENU_ICONS: () => MENU_ICONS,
|
|
43
|
-
MESSAGE_ACTION_ICONS: () => MESSAGE_ACTION_ICONS,
|
|
44
42
|
MessageActions: () => MessageActions,
|
|
45
43
|
MessageBubble: () => MessageBubble,
|
|
46
44
|
PartRenderer: () => PartRenderer,
|
|
47
45
|
applyChatEvent: () => applyChatEvent,
|
|
48
46
|
buildChatScope: () => buildChatScope,
|
|
49
47
|
collectMessageText: () => collectMessageText,
|
|
48
|
+
createChatComponentRegistry: () => createChatComponentRegistry,
|
|
50
49
|
createChatId: () => createChatId,
|
|
51
50
|
createChatRuntime: () => createChatRuntime,
|
|
52
51
|
createChatWorkspace: () => createChatWorkspace,
|
|
@@ -858,8 +857,8 @@ function useChatAutoScroll({
|
|
|
858
857
|
}
|
|
859
858
|
|
|
860
859
|
// src/chat-composition.tsx
|
|
861
|
-
var
|
|
862
|
-
var
|
|
860
|
+
var import_runtime5 = require("@pactor-app/runtime");
|
|
861
|
+
var import_react16 = require("react");
|
|
863
862
|
|
|
864
863
|
// src/hooks/use-chat-model.ts
|
|
865
864
|
var import_react3 = require("react");
|
|
@@ -884,121 +883,274 @@ function useChatModel({
|
|
|
884
883
|
}
|
|
885
884
|
|
|
886
885
|
// src/view/AppShell.tsx
|
|
887
|
-
var
|
|
888
|
-
var import_react4 = require("react");
|
|
886
|
+
var import_components = require("@pactor-app/ui/components");
|
|
889
887
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
890
|
-
var SidebarDrawerContext = (0, import_react4.createContext)(null);
|
|
891
888
|
function useSidebarDrawer() {
|
|
892
|
-
return (0,
|
|
889
|
+
return (0, import_components.useSidebarDrawer)();
|
|
893
890
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
function AppShell({ sidebar, brand, locationKey, sidebarFooter, collapsible = false, children, className }) {
|
|
914
|
-
const [drawerOpen, setDrawerOpen] = (0, import_react4.useState)(false);
|
|
915
|
-
const isMobile = useIsMobileViewport();
|
|
916
|
-
const close = (0, import_react4.useCallback)(() => setDrawerOpen(false), []);
|
|
917
|
-
const [collapsed, setCollapsed] = (0, import_react4.useState)(false);
|
|
918
|
-
const collapsedEffective = collapsible && collapsed && !isMobile;
|
|
919
|
-
const framed = brand !== void 0 || sidebarFooter !== void 0;
|
|
920
|
-
const [trackedLocationKey, setTrackedLocationKey] = (0, import_react4.useState)(locationKey);
|
|
921
|
-
if (trackedLocationKey !== locationKey) {
|
|
922
|
-
setTrackedLocationKey(locationKey);
|
|
923
|
-
setDrawerOpen(false);
|
|
924
|
-
}
|
|
925
|
-
(0, import_react4.useEffect)(() => {
|
|
926
|
-
if (!drawerOpen) {
|
|
927
|
-
return;
|
|
891
|
+
function AppShell({
|
|
892
|
+
sidebar,
|
|
893
|
+
brand,
|
|
894
|
+
locationKey,
|
|
895
|
+
sidebarFooter,
|
|
896
|
+
collapsible = false,
|
|
897
|
+
children,
|
|
898
|
+
className
|
|
899
|
+
}) {
|
|
900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
901
|
+
import_components.Sidebar,
|
|
902
|
+
{
|
|
903
|
+
content: sidebar,
|
|
904
|
+
brand,
|
|
905
|
+
locationKey,
|
|
906
|
+
sidebarFooter,
|
|
907
|
+
collapsible,
|
|
908
|
+
className: `pactor-chat-shell h-full min-h-0${className ? ` ${className}` : ""}`,
|
|
909
|
+
children
|
|
928
910
|
}
|
|
929
|
-
|
|
930
|
-
if (event.key === "Escape") {
|
|
931
|
-
setDrawerOpen(false);
|
|
932
|
-
}
|
|
933
|
-
};
|
|
934
|
-
window.addEventListener("keydown", onKeyDown);
|
|
935
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
936
|
-
}, [drawerOpen]);
|
|
937
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarDrawerContext.Provider, { value: { close, collapsed: collapsedEffective }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `pactor-chat-shell${className ? ` ${className}` : ""}`, children: [
|
|
938
|
-
drawerOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-chat-shell__scrim", "aria-hidden": true, onClick: close }) : null,
|
|
939
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
940
|
-
"div",
|
|
941
|
-
{
|
|
942
|
-
className: `pactor-chat-shell__sidebar${framed ? " pactor-chat-shell__sidebar--framed" : ""}${collapsedEffective ? " pactor-chat-shell__sidebar--collapsed" : ""}`,
|
|
943
|
-
"data-open": drawerOpen ? "true" : "false",
|
|
944
|
-
inert: isMobile && !drawerOpen ? true : void 0,
|
|
945
|
-
children: framed ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
946
|
-
brand !== void 0 && // 桌面品牌行(决策 D3):brand 左、折叠钮右;移动端由
|
|
947
|
-
// CSS 隐藏(品牌维持顶栏现状)
|
|
948
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pactor-chat-shell__sidebar-header", children: [
|
|
949
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-chat-shell__brand", children: brand }),
|
|
950
|
-
collapsible && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
951
|
-
"button",
|
|
952
|
-
{
|
|
953
|
-
type: "button",
|
|
954
|
-
className: "pactor-chat-icon-button pactor-chat-shell__collapse",
|
|
955
|
-
"aria-label": collapsedEffective ? "\u5C55\u5F00\u4FA7\u680F" : "\u6298\u53E0\u4FA7\u680F",
|
|
956
|
-
"aria-expanded": !collapsedEffective,
|
|
957
|
-
title: collapsedEffective ? "\u5C55\u5F00\u4FA7\u680F" : "\u6298\u53E0\u4FA7\u680F",
|
|
958
|
-
onClick: () => setCollapsed((value) => !value),
|
|
959
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.PanelLeft, { size: 16, strokeWidth: 1.7 })
|
|
960
|
-
}
|
|
961
|
-
)
|
|
962
|
-
] }),
|
|
963
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-chat-shell__sidebar-body", children: sidebar }),
|
|
964
|
-
sidebarFooter !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-chat-shell__sidebar-footer", children: sidebarFooter })
|
|
965
|
-
] }) : sidebar
|
|
966
|
-
}
|
|
967
|
-
),
|
|
968
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", { className: "pactor-chat-shell__main", children: [
|
|
969
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pactor-chat-shell__topbar", children: [
|
|
970
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
971
|
-
"button",
|
|
972
|
-
{
|
|
973
|
-
type: "button",
|
|
974
|
-
className: "pactor-chat-icon-button pactor-chat-shell__menu",
|
|
975
|
-
"aria-label": "\u6253\u5F00\u5BFC\u822A",
|
|
976
|
-
"aria-expanded": drawerOpen,
|
|
977
|
-
onClick: () => setDrawerOpen(true),
|
|
978
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Menu, { size: 18, strokeWidth: 1.7 })
|
|
979
|
-
}
|
|
980
|
-
),
|
|
981
|
-
brand
|
|
982
|
-
] }),
|
|
983
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-chat-shell__content", children })
|
|
984
|
-
] })
|
|
985
|
-
] }) });
|
|
911
|
+
);
|
|
986
912
|
}
|
|
987
913
|
|
|
988
914
|
// src/view/ArtifactPanel.tsx
|
|
989
|
-
var
|
|
915
|
+
var import_components4 = require("@pactor-app/ui/components");
|
|
990
916
|
var import_core3 = require("@pactor-app/core");
|
|
991
917
|
var import_markdown2 = require("@pactor-app/markdown");
|
|
992
|
-
var
|
|
918
|
+
var import_runtime4 = require("@pactor-app/runtime");
|
|
993
919
|
var import_react5 = require("react");
|
|
994
920
|
|
|
995
921
|
// src/view/PartRenderer.tsx
|
|
996
|
-
var
|
|
922
|
+
var import_components2 = require("@pactor-app/ui/components");
|
|
997
923
|
var import_markdown = require("@pactor-app/markdown");
|
|
924
|
+
var import_runtime3 = require("@pactor-app/runtime");
|
|
925
|
+
|
|
926
|
+
// src/view/chrome/artifact-card.tsx
|
|
927
|
+
function buildArtifactCardFragment(artifact) {
|
|
928
|
+
return {
|
|
929
|
+
requires: ["Card", "Flex", "Text", "Badge", "Button"],
|
|
930
|
+
node: {
|
|
931
|
+
type: "Card",
|
|
932
|
+
props: { className: "pactor-chat-artifact-card" },
|
|
933
|
+
children: [
|
|
934
|
+
{
|
|
935
|
+
type: "Flex",
|
|
936
|
+
props: { justify: "space-between", align: "center", gap: "small" },
|
|
937
|
+
children: [
|
|
938
|
+
{
|
|
939
|
+
type: "Text",
|
|
940
|
+
props: {
|
|
941
|
+
text: artifact.title,
|
|
942
|
+
strong: true,
|
|
943
|
+
className: "pactor-chat-artifact-card__title"
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
type: "Badge",
|
|
948
|
+
props: {
|
|
949
|
+
text: artifact.kind,
|
|
950
|
+
variant: "secondary",
|
|
951
|
+
className: "pactor-chat-artifact-card__kind"
|
|
952
|
+
}
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
type: "Button",
|
|
956
|
+
props: {
|
|
957
|
+
text: "\u5728\u9762\u677F\u4E2D\u6253\u5F00",
|
|
958
|
+
variant: "default",
|
|
959
|
+
size: "small",
|
|
960
|
+
className: "pactor-chat-artifact-card__open"
|
|
961
|
+
},
|
|
962
|
+
events: {
|
|
963
|
+
onClick: [
|
|
964
|
+
{
|
|
965
|
+
action: "chat.openArtifact",
|
|
966
|
+
params: { artifact }
|
|
967
|
+
}
|
|
968
|
+
]
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
]
|
|
972
|
+
}
|
|
973
|
+
]
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// src/view/chrome/ChromeSlot.tsx
|
|
998
979
|
var import_runtime2 = require("@pactor-app/runtime");
|
|
980
|
+
var import_react4 = require("react");
|
|
981
|
+
|
|
982
|
+
// src/view/chrome/actions.ts
|
|
983
|
+
var handlers = {};
|
|
984
|
+
function setChatChromeHandlers(next) {
|
|
985
|
+
handlers = { ...handlers, ...next };
|
|
986
|
+
}
|
|
987
|
+
var messageActionDispatchers = /* @__PURE__ */ new Map();
|
|
988
|
+
function setMessageActionDispatcher(token, dispatch) {
|
|
989
|
+
messageActionDispatchers.set(token, dispatch);
|
|
990
|
+
}
|
|
991
|
+
function clearMessageActionDispatcher(token) {
|
|
992
|
+
messageActionDispatchers.delete(token);
|
|
993
|
+
}
|
|
994
|
+
var CHROME_ACTION_HANDLERS = {
|
|
995
|
+
"chat.sendSuggestion": (action) => {
|
|
996
|
+
const text = action.params?.["text"];
|
|
997
|
+
if (typeof text === "string") {
|
|
998
|
+
handlers.sendSuggestion?.(text);
|
|
999
|
+
}
|
|
1000
|
+
return { ok: true };
|
|
1001
|
+
},
|
|
1002
|
+
"chat.openArtifact": (action) => {
|
|
1003
|
+
const artifact = action.params?.["artifact"];
|
|
1004
|
+
if (artifact) {
|
|
1005
|
+
handlers.openArtifact?.(artifact);
|
|
1006
|
+
}
|
|
1007
|
+
return { ok: true };
|
|
1008
|
+
},
|
|
1009
|
+
"chat.messageAction": (action) => {
|
|
1010
|
+
const token = action.params?.["token"];
|
|
1011
|
+
const actionId = action.params?.["actionId"];
|
|
1012
|
+
if (typeof token === "string" && typeof actionId === "string") {
|
|
1013
|
+
messageActionDispatchers.get(token)?.(actionId);
|
|
1014
|
+
}
|
|
1015
|
+
return { ok: true };
|
|
1016
|
+
},
|
|
1017
|
+
"chat.composerSubmit": (action) => {
|
|
1018
|
+
const value = action.params?.["value"];
|
|
1019
|
+
if (typeof value === "string") {
|
|
1020
|
+
handlers.composerSubmit?.(value);
|
|
1021
|
+
}
|
|
1022
|
+
return { ok: true };
|
|
1023
|
+
},
|
|
1024
|
+
"chat.menuSelect": (action) => {
|
|
1025
|
+
const key = action.params?.["key"];
|
|
1026
|
+
if (typeof key === "string") {
|
|
1027
|
+
handlers.menuSelect?.(key);
|
|
1028
|
+
}
|
|
1029
|
+
return { ok: true };
|
|
1030
|
+
},
|
|
1031
|
+
"chat.modelChange": (action) => {
|
|
1032
|
+
const value = action.params?.["value"];
|
|
1033
|
+
if (typeof value === "string") {
|
|
1034
|
+
handlers.modelChange?.(value);
|
|
1035
|
+
}
|
|
1036
|
+
return { ok: true };
|
|
1037
|
+
},
|
|
1038
|
+
"chat.headerAction": (action) => {
|
|
1039
|
+
const name = action.params?.["action"];
|
|
1040
|
+
if (typeof name === "string") {
|
|
1041
|
+
handlers.headerAction?.(name);
|
|
1042
|
+
}
|
|
1043
|
+
return { ok: true };
|
|
1044
|
+
},
|
|
1045
|
+
"chat.panelClose": () => {
|
|
1046
|
+
handlers.panelClose?.();
|
|
1047
|
+
return { ok: true };
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
function ensureChatChromeActions(actions) {
|
|
1051
|
+
for (const [name, handler] of Object.entries(CHROME_ACTION_HANDLERS)) {
|
|
1052
|
+
if (!actions.has(name)) {
|
|
1053
|
+
actions.register(name, handler);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
function invokeChatPanelClose() {
|
|
1058
|
+
handlers.panelClose?.();
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// src/view/chrome/ChromeSlot.tsx
|
|
999
1062
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1063
|
+
var warnedMissing = /* @__PURE__ */ new Set();
|
|
1064
|
+
function warnMissingOnce(key, detail) {
|
|
1065
|
+
if (!warnedMissing.has(key)) {
|
|
1066
|
+
warnedMissing.add(key);
|
|
1067
|
+
console.warn(`[@pactor-app/chat] ${detail}`);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
function ChromeSlotInner({
|
|
1071
|
+
fragment,
|
|
1072
|
+
fallback,
|
|
1073
|
+
components,
|
|
1074
|
+
wrap
|
|
1075
|
+
}) {
|
|
1076
|
+
let renderer;
|
|
1077
|
+
try {
|
|
1078
|
+
renderer = (0, import_runtime2.useRenderer)();
|
|
1079
|
+
} catch {
|
|
1080
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
|
|
1081
|
+
}
|
|
1082
|
+
ensureChatChromeActions(renderer.context.actions);
|
|
1083
|
+
if (components) {
|
|
1084
|
+
for (const [name, component] of Object.entries(components)) {
|
|
1085
|
+
const existing = renderer.context.components.get(name);
|
|
1086
|
+
if (existing !== void 0 && existing !== component) {
|
|
1087
|
+
warnMissingOnce(
|
|
1088
|
+
`conflict:${name}`,
|
|
1089
|
+
`[@pactor-app/chat] chrome \u5185\u90E8\u7EC4\u4EF6\u540D\u300C${name}\u300D\u88AB\u5BBF\u4E3B\u5360\u7528\uFF0C\u5DF2\u56DE\u9000\u5185\u5EFA\u5B9E\u73B0`
|
|
1090
|
+
);
|
|
1091
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
|
|
1092
|
+
}
|
|
1093
|
+
if (existing === void 0) {
|
|
1094
|
+
renderer.context.components.register(
|
|
1095
|
+
name,
|
|
1096
|
+
component
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
const missing = fragment.requires.filter(
|
|
1102
|
+
(type) => !renderer.context.components.has(type)
|
|
1103
|
+
);
|
|
1104
|
+
if (missing.length > 0) {
|
|
1105
|
+
warnMissingOnce(
|
|
1106
|
+
`${fragment.node.type}:${missing.join(",")}`,
|
|
1107
|
+
`[@pactor-app/chat] chrome DSL \u7247\u6BB5\u6240\u9700\u7EC4\u4EF6\u7C7B\u578B\u7F3A\u5931\uFF08${missing.join(" / ")}\uFF09\uFF0C\u5DF2\u56DE\u9000\u5185\u5EFA\u5B9E\u73B0`
|
|
1108
|
+
);
|
|
1109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
|
|
1110
|
+
}
|
|
1111
|
+
const rendered = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
|
|
1112
|
+
return wrap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: wrap(rendered) }) : rendered;
|
|
1113
|
+
}
|
|
1114
|
+
var ChromeSlotGuard = class extends import_react4.Component {
|
|
1115
|
+
constructor() {
|
|
1116
|
+
super(...arguments);
|
|
1117
|
+
this.state = { failed: false };
|
|
1118
|
+
}
|
|
1119
|
+
static getDerivedStateFromError() {
|
|
1120
|
+
return { failed: true };
|
|
1121
|
+
}
|
|
1122
|
+
render() {
|
|
1123
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
function ChromeSlot(props) {
|
|
1127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChromeSlotGuard, { fallback: props.fallback, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChromeSlotInner, { ...props }) });
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// src/view/chrome/feedback.tsx
|
|
1131
|
+
function buildErrorFragment(message) {
|
|
1132
|
+
return {
|
|
1133
|
+
requires: ["Alert"],
|
|
1134
|
+
node: {
|
|
1135
|
+
type: "Alert",
|
|
1136
|
+
props: { variant: "error", message }
|
|
1137
|
+
}
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
function buildStatusFragment(text) {
|
|
1141
|
+
return {
|
|
1142
|
+
requires: ["Text"],
|
|
1143
|
+
node: {
|
|
1144
|
+
type: "Text",
|
|
1145
|
+
props: { type: "secondary", text }
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// src/view/PartRenderer.tsx
|
|
1151
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1000
1152
|
function ChatDenied({ deniedType }) {
|
|
1001
|
-
return /* @__PURE__ */ (0,
|
|
1153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pactor-chat-denied", "data-pactor-chat-denied": deniedType, children: [
|
|
1002
1154
|
"\u8BE5\u7EC4\u4EF6\u4E0D\u5141\u8BB8\u5728 Chat \u4E2D\u4F7F\u7528",
|
|
1003
1155
|
deniedType ? `\uFF1A${deniedType}` : ""
|
|
1004
1156
|
] });
|
|
@@ -1007,64 +1159,90 @@ function ChatDslNode({
|
|
|
1007
1159
|
node,
|
|
1008
1160
|
scope
|
|
1009
1161
|
}) {
|
|
1010
|
-
const renderer = (0,
|
|
1162
|
+
const renderer = (0, import_runtime3.useRenderer)();
|
|
1011
1163
|
const extraScope = scope ? buildChatScope(scope) : void 0;
|
|
1012
|
-
return /* @__PURE__ */ (0,
|
|
1164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderer.renderChildren([node], extraScope) });
|
|
1013
1165
|
}
|
|
1014
1166
|
function SmoothText({ content, streaming }) {
|
|
1015
1167
|
const shown = useSmoothStreamText(content, streaming);
|
|
1016
|
-
return /* @__PURE__ */ (0,
|
|
1168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-text", children: shown });
|
|
1017
1169
|
}
|
|
1018
1170
|
function SmoothMarkdown({ content, streaming }) {
|
|
1019
1171
|
const shown = useSmoothStreamText(content, streaming);
|
|
1020
|
-
return /* @__PURE__ */ (0,
|
|
1172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_markdown.MarkdownRenderer, { content: shown });
|
|
1021
1173
|
}
|
|
1022
1174
|
function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact }) {
|
|
1023
1175
|
switch (part.type) {
|
|
1024
1176
|
case "text":
|
|
1025
|
-
return /* @__PURE__ */ (0,
|
|
1177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SmoothText, { content: part.content, streaming });
|
|
1026
1178
|
case "markdown":
|
|
1027
|
-
return /* @__PURE__ */ (0,
|
|
1179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SmoothMarkdown, { content: part.content, streaming });
|
|
1028
1180
|
case "thinking":
|
|
1029
1181
|
case "tool-call":
|
|
1030
1182
|
case "tool-result":
|
|
1031
1183
|
return null;
|
|
1032
1184
|
case "dsl": {
|
|
1033
1185
|
if (!part.schema || !runtime) {
|
|
1034
|
-
return /* @__PURE__ */ (0,
|
|
1186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1187
|
+
ChromeSlot,
|
|
1188
|
+
{
|
|
1189
|
+
fragment: buildStatusFragment(
|
|
1190
|
+
part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026"
|
|
1191
|
+
),
|
|
1192
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-dsl-pending", children: part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026" })
|
|
1193
|
+
}
|
|
1194
|
+
);
|
|
1035
1195
|
}
|
|
1036
1196
|
const guarded = guardChatDsl(part.schema, runtime.context.components);
|
|
1037
|
-
return /* @__PURE__ */ (0,
|
|
1197
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-dsl", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_runtime3.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatDslNode, { node: guarded, scope }) }) });
|
|
1038
1198
|
}
|
|
1039
1199
|
case "error":
|
|
1040
|
-
return /* @__PURE__ */ (0,
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1201
|
+
ChromeSlot,
|
|
1202
|
+
{
|
|
1203
|
+
fragment: buildErrorFragment(part.message),
|
|
1204
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pactor-chat-error", role: "alert", children: [
|
|
1205
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.Icon, { name: "error", size: 14 }),
|
|
1206
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: part.message })
|
|
1207
|
+
] })
|
|
1208
|
+
}
|
|
1209
|
+
);
|
|
1044
1210
|
case "status":
|
|
1045
|
-
return /* @__PURE__ */ (0,
|
|
1211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1212
|
+
ChromeSlot,
|
|
1213
|
+
{
|
|
1214
|
+
fragment: buildStatusFragment(part.text),
|
|
1215
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-status", children: part.text })
|
|
1216
|
+
}
|
|
1217
|
+
);
|
|
1046
1218
|
case "artifact":
|
|
1047
|
-
return /* @__PURE__ */ (0,
|
|
1048
|
-
|
|
1219
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1220
|
+
ChromeSlot,
|
|
1049
1221
|
{
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1222
|
+
fragment: buildArtifactCardFragment(part.artifact),
|
|
1223
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1224
|
+
"div",
|
|
1225
|
+
{
|
|
1226
|
+
className: "pactor-chat-artifact-card",
|
|
1227
|
+
"data-artifact-kind": part.artifact.kind,
|
|
1228
|
+
children: [
|
|
1229
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "pactor-chat-artifact-card__title", children: part.artifact.title }),
|
|
1230
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "pactor-chat-artifact-card__kind", children: part.artifact.kind }),
|
|
1231
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1232
|
+
"button",
|
|
1233
|
+
{
|
|
1234
|
+
type: "button",
|
|
1235
|
+
className: "pactor-chat-artifact-card__open",
|
|
1236
|
+
onClick: () => onOpenArtifact?.(part.artifact),
|
|
1237
|
+
children: [
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.Icon, { name: "panel-right-open", size: 13, strokeWidth: 1.7 }),
|
|
1239
|
+
"\u5728\u9762\u677F\u4E2D\u6253\u5F00"
|
|
1240
|
+
]
|
|
1241
|
+
}
|
|
1242
|
+
)
|
|
1243
|
+
]
|
|
1244
|
+
}
|
|
1245
|
+
)
|
|
1068
1246
|
}
|
|
1069
1247
|
);
|
|
1070
1248
|
default:
|
|
@@ -1072,8 +1250,65 @@ function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact
|
|
|
1072
1250
|
}
|
|
1073
1251
|
}
|
|
1074
1252
|
|
|
1253
|
+
// src/view/chrome/panel-header.tsx
|
|
1254
|
+
var import_components3 = require("@pactor-app/ui/components");
|
|
1255
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1256
|
+
function ChatPanelCloseButton() {
|
|
1257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1258
|
+
"button",
|
|
1259
|
+
{
|
|
1260
|
+
type: "button",
|
|
1261
|
+
className: "pactor-chat-icon-button pactor-chat-inspector__close",
|
|
1262
|
+
title: "\u5173\u95ED\u9762\u677F",
|
|
1263
|
+
"aria-label": "\u5173\u95ED\u9762\u677F",
|
|
1264
|
+
onClick: () => invokeChatPanelClose(),
|
|
1265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components3.Icon, { name: "x", size: 16 })
|
|
1266
|
+
}
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
1269
|
+
var PANEL_HEADER_INTERNAL_COMPONENTS = { ChatPanelCloseButton };
|
|
1270
|
+
function buildPanelHeaderFragment(props) {
|
|
1271
|
+
return {
|
|
1272
|
+
requires: ["Flex", "Text", "Badge", "ChatPanelCloseButton"],
|
|
1273
|
+
node: {
|
|
1274
|
+
type: "Flex",
|
|
1275
|
+
props: {
|
|
1276
|
+
justify: "space-between",
|
|
1277
|
+
align: "center",
|
|
1278
|
+
gap: "small",
|
|
1279
|
+
className: "pactor-chat-inspector__header-dsl"
|
|
1280
|
+
},
|
|
1281
|
+
children: [
|
|
1282
|
+
{
|
|
1283
|
+
type: "Flex",
|
|
1284
|
+
props: { align: "center", gap: "small" },
|
|
1285
|
+
children: [
|
|
1286
|
+
{
|
|
1287
|
+
type: "Text",
|
|
1288
|
+
props: {
|
|
1289
|
+
text: props.title,
|
|
1290
|
+
strong: true,
|
|
1291
|
+
className: "pactor-chat-inspector__title"
|
|
1292
|
+
}
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
type: "Badge",
|
|
1296
|
+
props: {
|
|
1297
|
+
text: props.kind,
|
|
1298
|
+
variant: "secondary",
|
|
1299
|
+
className: "pactor-chat-inspector__kind"
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
]
|
|
1303
|
+
},
|
|
1304
|
+
{ type: "ChatPanelCloseButton" }
|
|
1305
|
+
]
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1075
1310
|
// src/view/ArtifactPanel.tsx
|
|
1076
|
-
var
|
|
1311
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1077
1312
|
function useArtifactRuntime(safeRegistry, user) {
|
|
1078
1313
|
return (0, import_react5.useMemo)(() => {
|
|
1079
1314
|
if (!safeRegistry) {
|
|
@@ -1099,12 +1334,12 @@ var ArtifactDslGuard = class extends import_react5.Component {
|
|
|
1099
1334
|
console.warn("[@pactor-app/chat] DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A", error);
|
|
1100
1335
|
}
|
|
1101
1336
|
render() {
|
|
1102
|
-
return this.state.failed ? /* @__PURE__ */ (0,
|
|
1337
|
+
return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-denied", children: "DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A" }) : this.props.children;
|
|
1103
1338
|
}
|
|
1104
1339
|
};
|
|
1105
1340
|
function ArtifactDslNode({ node }) {
|
|
1106
|
-
const { renderChildren } = (0,
|
|
1107
|
-
return /* @__PURE__ */ (0,
|
|
1341
|
+
const { renderChildren } = (0, import_runtime4.useRenderer)();
|
|
1342
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: renderChildren([node]) });
|
|
1108
1343
|
}
|
|
1109
1344
|
function ArtifactDslContent({
|
|
1110
1345
|
content,
|
|
@@ -1112,10 +1347,10 @@ function ArtifactDslContent({
|
|
|
1112
1347
|
}) {
|
|
1113
1348
|
const node = typeof content === "object" && content !== null && !Array.isArray(content) && typeof content.type === "string" ? content : void 0;
|
|
1114
1349
|
if (!node || !runtime) {
|
|
1115
|
-
return /* @__PURE__ */ (0,
|
|
1350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-denied", children: node ? "DSL \u9884\u89C8\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "DSL \u4EA7\u51FA\u7269\u5185\u5BB9\u65E0\u6548" });
|
|
1116
1351
|
}
|
|
1117
1352
|
const guarded = guardChatDsl(node, runtime.context.components);
|
|
1118
|
-
return /* @__PURE__ */ (0,
|
|
1353
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_runtime4.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslNode, { node: guarded }) }) });
|
|
1119
1354
|
}
|
|
1120
1355
|
function ArtifactContent({
|
|
1121
1356
|
artifact,
|
|
@@ -1123,16 +1358,16 @@ function ArtifactContent({
|
|
|
1123
1358
|
}) {
|
|
1124
1359
|
switch (artifact.kind) {
|
|
1125
1360
|
case "markdown":
|
|
1126
|
-
return /* @__PURE__ */ (0,
|
|
1361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_markdown2.MarkdownRenderer, { content: String(artifact.content) });
|
|
1127
1362
|
case "code":
|
|
1128
|
-
return /* @__PURE__ */ (0,
|
|
1129
|
-
artifact.language ? /* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "pactor-chat-inspector__code", children: [
|
|
1364
|
+
artifact.language ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__code-lang", children: artifact.language }) : null,
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: String(artifact.content) }) })
|
|
1131
1366
|
] });
|
|
1132
1367
|
case "text":
|
|
1133
|
-
return /* @__PURE__ */ (0,
|
|
1368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { className: "pactor-chat-inspector__text", children: String(artifact.content) });
|
|
1134
1369
|
case "dsl":
|
|
1135
|
-
return /* @__PURE__ */ (0,
|
|
1370
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslContent, { content: artifact.content, runtime });
|
|
1136
1371
|
default:
|
|
1137
1372
|
return null;
|
|
1138
1373
|
}
|
|
@@ -1146,6 +1381,11 @@ function ArtifactPanel({
|
|
|
1146
1381
|
className
|
|
1147
1382
|
}) {
|
|
1148
1383
|
const runtime = useArtifactRuntime(safeRegistry, user);
|
|
1384
|
+
const closeRef = (0, import_react5.useRef)(onClose);
|
|
1385
|
+
closeRef.current = onClose;
|
|
1386
|
+
(0, import_react5.useEffect)(() => {
|
|
1387
|
+
setChatChromeHandlers({ panelClose: () => closeRef.current?.() });
|
|
1388
|
+
}, []);
|
|
1149
1389
|
const panelRef = (0, import_react5.useRef)(null);
|
|
1150
1390
|
const [width, setWidth] = (0, import_react5.useState)(null);
|
|
1151
1391
|
const handleResizeStart = (event) => {
|
|
@@ -1173,7 +1413,7 @@ function ArtifactPanel({
|
|
|
1173
1413
|
document.addEventListener("pointermove", onMove);
|
|
1174
1414
|
document.addEventListener("pointerup", onUp);
|
|
1175
1415
|
};
|
|
1176
|
-
return /* @__PURE__ */ (0,
|
|
1416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1177
1417
|
"aside",
|
|
1178
1418
|
{
|
|
1179
1419
|
ref: panelRef,
|
|
@@ -1181,7 +1421,7 @@ function ArtifactPanel({
|
|
|
1181
1421
|
"data-kind": artifact?.kind,
|
|
1182
1422
|
style: width !== null ? { width: `${width}px` } : void 0,
|
|
1183
1423
|
children: [
|
|
1184
|
-
/* @__PURE__ */ (0,
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1185
1425
|
"div",
|
|
1186
1426
|
{
|
|
1187
1427
|
className: "pactor-chat-inspector__resize",
|
|
@@ -1191,38 +1431,48 @@ function ArtifactPanel({
|
|
|
1191
1431
|
onPointerDown: handleResizeStart
|
|
1192
1432
|
}
|
|
1193
1433
|
),
|
|
1194
|
-
/* @__PURE__ */ (0,
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1435
|
+
ChromeSlot,
|
|
1436
|
+
{
|
|
1437
|
+
fragment: buildPanelHeaderFragment({
|
|
1438
|
+
title: artifact?.title ?? "\u4EA7\u51FA\u7269",
|
|
1439
|
+
kind: artifact?.kind ?? "text"
|
|
1440
|
+
}),
|
|
1441
|
+
components: PANEL_HEADER_INTERNAL_COMPONENTS,
|
|
1442
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__title", children: artifact?.title ?? "\u4EA7\u51FA\u7269" }),
|
|
1444
|
+
artifact ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__kind", children: artifact.kind }) : null,
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1446
|
+
"button",
|
|
1447
|
+
{
|
|
1448
|
+
type: "button",
|
|
1449
|
+
className: "pactor-chat-icon-button pactor-chat-inspector__close",
|
|
1450
|
+
"aria-label": "\u5173\u95ED\u9762\u677F",
|
|
1451
|
+
onClick: onClose,
|
|
1452
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "x", size: 16, strokeWidth: 1.7 })
|
|
1453
|
+
}
|
|
1454
|
+
)
|
|
1455
|
+
] })
|
|
1456
|
+
}
|
|
1457
|
+
) }),
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__body", children: inspector !== void 0 && inspector !== null ? inspector : artifact ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactContent, { artifact, runtime }) : null })
|
|
1209
1459
|
]
|
|
1210
1460
|
}
|
|
1211
1461
|
);
|
|
1212
1462
|
}
|
|
1213
1463
|
|
|
1214
1464
|
// src/view/ChatView.tsx
|
|
1215
|
-
var
|
|
1465
|
+
var import_components10 = require("@pactor-app/ui/components");
|
|
1216
1466
|
var import_core4 = require("@pactor-app/core");
|
|
1217
|
-
var
|
|
1467
|
+
var import_react14 = require("react");
|
|
1218
1468
|
|
|
1219
1469
|
// src/view/Composer.tsx
|
|
1220
|
-
var
|
|
1221
|
-
var
|
|
1470
|
+
var import_components7 = require("@pactor-app/ui/components");
|
|
1471
|
+
var import_react10 = require("react");
|
|
1222
1472
|
|
|
1223
1473
|
// src/view/AnchoredPopover.tsx
|
|
1224
1474
|
var import_react6 = require("react");
|
|
1225
|
-
var
|
|
1475
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1226
1476
|
function AnchoredPopover({
|
|
1227
1477
|
anchorRect,
|
|
1228
1478
|
onClose,
|
|
@@ -1279,7 +1529,7 @@ function AnchoredPopover({
|
|
|
1279
1529
|
position?.below ? "pactor-chat-popover--below" : "",
|
|
1280
1530
|
className ?? ""
|
|
1281
1531
|
].filter(Boolean).join(" ");
|
|
1282
|
-
return /* @__PURE__ */ (0,
|
|
1532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1283
1533
|
"div",
|
|
1284
1534
|
{
|
|
1285
1535
|
ref,
|
|
@@ -1298,9 +1548,34 @@ function AnchoredPopover({
|
|
|
1298
1548
|
}
|
|
1299
1549
|
|
|
1300
1550
|
// src/view/ModelChip.tsx
|
|
1301
|
-
var
|
|
1551
|
+
var import_components5 = require("@pactor-app/ui/components");
|
|
1302
1552
|
var import_react7 = require("react");
|
|
1303
|
-
|
|
1553
|
+
|
|
1554
|
+
// src/view/chrome/model-select.tsx
|
|
1555
|
+
function buildModelSelectFragment(props) {
|
|
1556
|
+
return {
|
|
1557
|
+
requires: ["Select"],
|
|
1558
|
+
node: {
|
|
1559
|
+
type: "Select",
|
|
1560
|
+
props: {
|
|
1561
|
+
options: props.models.map((option) => ({
|
|
1562
|
+
value: option.value,
|
|
1563
|
+
label: option.label
|
|
1564
|
+
})),
|
|
1565
|
+
value: props.model,
|
|
1566
|
+
className: "pactor-chat-model-select"
|
|
1567
|
+
},
|
|
1568
|
+
events: {
|
|
1569
|
+
onChange: [
|
|
1570
|
+
{ action: "chat.modelChange", params: { value: "${event}" } }
|
|
1571
|
+
]
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// src/view/ModelChip.tsx
|
|
1578
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1304
1579
|
function ModelChip({
|
|
1305
1580
|
models,
|
|
1306
1581
|
model,
|
|
@@ -1309,8 +1584,8 @@ function ModelChip({
|
|
|
1309
1584
|
const chipRef = (0, import_react7.useRef)(null);
|
|
1310
1585
|
const [anchor, setAnchor] = (0, import_react7.useState)(null);
|
|
1311
1586
|
const currentOption = models.find((option) => option.value === model) ?? models[0];
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1588
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1314
1589
|
"button",
|
|
1315
1590
|
{
|
|
1316
1591
|
ref: chipRef,
|
|
@@ -1320,18 +1595,18 @@ function ModelChip({
|
|
|
1320
1595
|
"aria-label": "\u9009\u62E9\u6A21\u578B",
|
|
1321
1596
|
onClick: () => setAnchor(chipRef.current.getBoundingClientRect()),
|
|
1322
1597
|
children: [
|
|
1323
|
-
/* @__PURE__ */ (0,
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
1598
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-model-chip__label", children: currentOption.label }),
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components5.Icon, { name: "chevrons-up-down", size: 12 })
|
|
1325
1600
|
]
|
|
1326
1601
|
}
|
|
1327
1602
|
),
|
|
1328
|
-
anchor && /* @__PURE__ */ (0,
|
|
1603
|
+
anchor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1329
1604
|
AnchoredPopover,
|
|
1330
1605
|
{
|
|
1331
1606
|
anchorRect: anchor,
|
|
1332
1607
|
onClose: () => setAnchor(null),
|
|
1333
1608
|
role: "listbox",
|
|
1334
|
-
children: models.map((option) => /* @__PURE__ */ (0,
|
|
1609
|
+
children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1335
1610
|
"button",
|
|
1336
1611
|
{
|
|
1337
1612
|
type: "button",
|
|
@@ -1343,8 +1618,8 @@ function ModelChip({
|
|
|
1343
1618
|
setAnchor(null);
|
|
1344
1619
|
},
|
|
1345
1620
|
children: [
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1347
|
-
option.value === currentOption.value && /* @__PURE__ */ (0,
|
|
1621
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-popover__item-label", children: option.label }),
|
|
1622
|
+
option.value === currentOption.value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components5.Icon, { name: "check", size: 13, className: "pactor-chat-popover__item-check" })
|
|
1348
1623
|
]
|
|
1349
1624
|
},
|
|
1350
1625
|
option.value
|
|
@@ -1353,10 +1628,243 @@ function ModelChip({
|
|
|
1353
1628
|
)
|
|
1354
1629
|
] });
|
|
1355
1630
|
}
|
|
1631
|
+
function ModelSelect({
|
|
1632
|
+
models,
|
|
1633
|
+
model,
|
|
1634
|
+
onModelChange
|
|
1635
|
+
}) {
|
|
1636
|
+
const changeRef = (0, import_react7.useRef)(onModelChange);
|
|
1637
|
+
changeRef.current = onModelChange;
|
|
1638
|
+
(0, import_react7.useEffect)(() => {
|
|
1639
|
+
setChatChromeHandlers({
|
|
1640
|
+
modelChange: (value) => changeRef.current?.(value)
|
|
1641
|
+
});
|
|
1642
|
+
}, []);
|
|
1643
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1644
|
+
ChromeSlot,
|
|
1645
|
+
{
|
|
1646
|
+
fragment: buildModelSelectFragment({ models, model }),
|
|
1647
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ModelChip, { models, model, onModelChange })
|
|
1648
|
+
}
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1356
1651
|
|
|
1357
|
-
// src/view/
|
|
1652
|
+
// src/view/chrome/composer.tsx
|
|
1653
|
+
var import_components6 = require("@pactor-app/ui/components");
|
|
1358
1654
|
var import_react8 = require("react");
|
|
1359
|
-
var
|
|
1655
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1656
|
+
var ComposerBridgeContext = (0, import_react8.createContext)(
|
|
1657
|
+
null
|
|
1658
|
+
);
|
|
1659
|
+
function useComposerBridge() {
|
|
1660
|
+
const bridge = (0, import_react8.useContext)(ComposerBridgeContext);
|
|
1661
|
+
if (!bridge) {
|
|
1662
|
+
throw new Error(
|
|
1663
|
+
"[@pactor-app/chat] ChatComposer* \u5185\u90E8\u7EC4\u4EF6\u4EC5\u53EF\u5728 Composer chrome \u7247\u6BB5\u5185\u6E32\u67D3"
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
return bridge;
|
|
1667
|
+
}
|
|
1668
|
+
function formatSize(bytes) {
|
|
1669
|
+
if (bytes < 1024) {
|
|
1670
|
+
return `${bytes} B`;
|
|
1671
|
+
}
|
|
1672
|
+
if (bytes < 1024 * 1024) {
|
|
1673
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1674
|
+
}
|
|
1675
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1676
|
+
}
|
|
1677
|
+
function ComposerAttachments({
|
|
1678
|
+
attachments,
|
|
1679
|
+
onRemove,
|
|
1680
|
+
onClick
|
|
1681
|
+
}) {
|
|
1682
|
+
if (attachments.length === 0) {
|
|
1683
|
+
return null;
|
|
1684
|
+
}
|
|
1685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "pactor-chat-composer__attachments", children: attachments.map((attachment) => {
|
|
1686
|
+
const isImage = attachment.mimeType.startsWith("image/");
|
|
1687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1688
|
+
"div",
|
|
1689
|
+
{
|
|
1690
|
+
className: "pactor-chat-composer__attachment",
|
|
1691
|
+
"data-attachment-id": attachment.id,
|
|
1692
|
+
onClick: () => onClick?.(attachment),
|
|
1693
|
+
children: [
|
|
1694
|
+
isImage && attachment.url ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "pactor-chat-composer__attachment-info", children: [
|
|
1695
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "file-text", size: 14 }),
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
|
|
1697
|
+
attachment.size !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
|
|
1698
|
+
] }),
|
|
1699
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1700
|
+
"button",
|
|
1701
|
+
{
|
|
1702
|
+
type: "button",
|
|
1703
|
+
className: "pactor-chat-icon-button pactor-chat-composer__attachment-remove",
|
|
1704
|
+
title: "\u79FB\u9664\u9644\u4EF6",
|
|
1705
|
+
"aria-label": "\u79FB\u9664\u9644\u4EF6",
|
|
1706
|
+
onClick: (event) => {
|
|
1707
|
+
event.stopPropagation();
|
|
1708
|
+
onRemove(attachment.id);
|
|
1709
|
+
},
|
|
1710
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "x", size: 12 })
|
|
1711
|
+
}
|
|
1712
|
+
)
|
|
1713
|
+
]
|
|
1714
|
+
},
|
|
1715
|
+
attachment.id
|
|
1716
|
+
);
|
|
1717
|
+
}) });
|
|
1718
|
+
}
|
|
1719
|
+
function ComposerContextChips({
|
|
1720
|
+
chips,
|
|
1721
|
+
onRemove
|
|
1722
|
+
}) {
|
|
1723
|
+
if (chips.length === 0) {
|
|
1724
|
+
return null;
|
|
1725
|
+
}
|
|
1726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "pactor-chat-composer__contexts", children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1727
|
+
"span",
|
|
1728
|
+
{
|
|
1729
|
+
className: "pactor-chat-context-chip",
|
|
1730
|
+
"data-context-id": chip.id,
|
|
1731
|
+
children: [
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-context-chip__label", children: chip.label }),
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1734
|
+
"button",
|
|
1735
|
+
{
|
|
1736
|
+
type: "button",
|
|
1737
|
+
className: "pactor-chat-icon-button pactor-chat-context-chip__remove",
|
|
1738
|
+
title: `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
|
|
1739
|
+
"aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
|
|
1740
|
+
onClick: () => onRemove(chip),
|
|
1741
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "x", size: 12 })
|
|
1742
|
+
}
|
|
1743
|
+
)
|
|
1744
|
+
]
|
|
1745
|
+
},
|
|
1746
|
+
`${chip.trigger ?? ""}:${chip.id}`
|
|
1747
|
+
)) });
|
|
1748
|
+
}
|
|
1749
|
+
function ChatComposerHeader() {
|
|
1750
|
+
const bridge = useComposerBridge();
|
|
1751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1752
|
+
bridge.attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1753
|
+
ComposerAttachments,
|
|
1754
|
+
{
|
|
1755
|
+
attachments: bridge.attachments,
|
|
1756
|
+
onRemove: bridge.removeAttachment,
|
|
1757
|
+
onClick: bridge.attachmentClick
|
|
1758
|
+
}
|
|
1759
|
+
),
|
|
1760
|
+
bridge.contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1761
|
+
ComposerContextChips,
|
|
1762
|
+
{
|
|
1763
|
+
chips: bridge.contextChips,
|
|
1764
|
+
onRemove: bridge.removeChip
|
|
1765
|
+
}
|
|
1766
|
+
)
|
|
1767
|
+
] });
|
|
1768
|
+
}
|
|
1769
|
+
function ChatComposerToolbarStart() {
|
|
1770
|
+
const bridge = useComposerBridge();
|
|
1771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1772
|
+
bridge.toolbarStart,
|
|
1773
|
+
bridge.showPlus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1774
|
+
"button",
|
|
1775
|
+
{
|
|
1776
|
+
type: "button",
|
|
1777
|
+
className: "pactor-chat-icon-button",
|
|
1778
|
+
title: "\u66F4\u591A\u529F\u80FD",
|
|
1779
|
+
"aria-label": "\u66F4\u591A\u529F\u80FD",
|
|
1780
|
+
onClick: (event) => bridge.plusClick(event.currentTarget.getBoundingClientRect()),
|
|
1781
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "plus", size: 14 })
|
|
1782
|
+
}
|
|
1783
|
+
),
|
|
1784
|
+
bridge.showAttach && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1785
|
+
"button",
|
|
1786
|
+
{
|
|
1787
|
+
type: "button",
|
|
1788
|
+
className: "pactor-chat-icon-button",
|
|
1789
|
+
title: "\u6DFB\u52A0\u9644\u4EF6",
|
|
1790
|
+
"aria-label": "\u6DFB\u52A0\u9644\u4EF6",
|
|
1791
|
+
onClick: bridge.openFilePicker,
|
|
1792
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "paperclip", size: 14 })
|
|
1793
|
+
}
|
|
1794
|
+
)
|
|
1795
|
+
] });
|
|
1796
|
+
}
|
|
1797
|
+
function ChatComposerToolbarEnd() {
|
|
1798
|
+
const bridge = useComposerBridge();
|
|
1799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1800
|
+
bridge.modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1801
|
+
ModelSelect,
|
|
1802
|
+
{
|
|
1803
|
+
models: bridge.models,
|
|
1804
|
+
model: bridge.model,
|
|
1805
|
+
onModelChange: bridge.modelChange
|
|
1806
|
+
}
|
|
1807
|
+
),
|
|
1808
|
+
bridge.toolbarEnd,
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1810
|
+
"button",
|
|
1811
|
+
{
|
|
1812
|
+
type: "button",
|
|
1813
|
+
className: `pactor-chat-composer__button${bridge.streaming ? " pactor-chat-composer__button--stop" : ""}`,
|
|
1814
|
+
title: bridge.streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
|
|
1815
|
+
"aria-label": bridge.streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
|
|
1816
|
+
disabled: bridge.streaming ? false : bridge.disabled || !bridge.text.trim(),
|
|
1817
|
+
onClick: bridge.streaming ? bridge.stop : bridge.send,
|
|
1818
|
+
children: bridge.streaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "arrow-up", size: 16 })
|
|
1819
|
+
}
|
|
1820
|
+
)
|
|
1821
|
+
] });
|
|
1822
|
+
}
|
|
1823
|
+
function ChatComposerFooter() {
|
|
1824
|
+
const bridge = useComposerBridge();
|
|
1825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: bridge.composerFooter });
|
|
1826
|
+
}
|
|
1827
|
+
var COMPOSER_INTERNAL_COMPONENTS = {
|
|
1828
|
+
ChatComposerHeader,
|
|
1829
|
+
ChatComposerToolbarStart,
|
|
1830
|
+
ChatComposerToolbarEnd,
|
|
1831
|
+
ChatComposerFooter
|
|
1832
|
+
};
|
|
1833
|
+
function buildComposerFragment(props) {
|
|
1834
|
+
const hideToolbar = props.hideToolbar === true;
|
|
1835
|
+
return {
|
|
1836
|
+
requires: [
|
|
1837
|
+
"ChatInput",
|
|
1838
|
+
"ChatComposerHeader",
|
|
1839
|
+
...hideToolbar ? [] : ["ChatComposerToolbarStart", "ChatComposerToolbarEnd"],
|
|
1840
|
+
"ChatComposerFooter"
|
|
1841
|
+
],
|
|
1842
|
+
node: {
|
|
1843
|
+
type: "ChatInput",
|
|
1844
|
+
props: {
|
|
1845
|
+
placeholder: props.placeholder,
|
|
1846
|
+
disabled: props.disabled,
|
|
1847
|
+
rows: 1,
|
|
1848
|
+
hideSend: true,
|
|
1849
|
+
header: { type: "ChatComposerHeader" },
|
|
1850
|
+
...hideToolbar ? {} : {
|
|
1851
|
+
toolbarStart: { type: "ChatComposerToolbarStart" },
|
|
1852
|
+
toolbarEnd: { type: "ChatComposerToolbarEnd" }
|
|
1853
|
+
},
|
|
1854
|
+
...props.hasFooter === true ? { footer: { type: "ChatComposerFooter" } } : {}
|
|
1855
|
+
},
|
|
1856
|
+
events: {
|
|
1857
|
+
onSubmit: [
|
|
1858
|
+
{ action: "chat.composerSubmit", params: { value: "${event}" } }
|
|
1859
|
+
]
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// src/view/context-sources.tsx
|
|
1866
|
+
var import_react9 = require("react");
|
|
1867
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1360
1868
|
function sourceCacheKey(source) {
|
|
1361
1869
|
return `${source.service ?? ""}:${JSON.stringify(source.params ?? {})}`;
|
|
1362
1870
|
}
|
|
@@ -1391,8 +1899,8 @@ function ContextSourceList({
|
|
|
1391
1899
|
cache,
|
|
1392
1900
|
onSelect
|
|
1393
1901
|
}) {
|
|
1394
|
-
const [resolutions, setResolutions] = (0,
|
|
1395
|
-
(0,
|
|
1902
|
+
const [resolutions, setResolutions] = (0, import_react9.useState)([]);
|
|
1903
|
+
(0, import_react9.useEffect)(() => {
|
|
1396
1904
|
let cancelled = false;
|
|
1397
1905
|
const initial = sources.map(
|
|
1398
1906
|
(source) => source.items ? { status: "ready", items: source.items } : { status: "loading" }
|
|
@@ -1437,12 +1945,12 @@ function ContextSourceList({
|
|
|
1437
1945
|
totalMatched += items.length;
|
|
1438
1946
|
return { source, resolution, items };
|
|
1439
1947
|
});
|
|
1440
|
-
return /* @__PURE__ */ (0,
|
|
1441
|
-
groups.map(({ source, resolution, items }) => /* @__PURE__ */ (0,
|
|
1442
|
-
sources.length > 1 && /* @__PURE__ */ (0,
|
|
1443
|
-
resolution.status === "loading" && /* @__PURE__ */ (0,
|
|
1444
|
-
resolution.status === "error" && /* @__PURE__ */ (0,
|
|
1445
|
-
items.map((item) => /* @__PURE__ */ (0,
|
|
1948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "pactor-chat-source-list", children: [
|
|
1949
|
+
groups.map(({ source, resolution, items }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "pactor-chat-source-list__group", children: [
|
|
1950
|
+
sources.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__group-label", children: source.label }),
|
|
1951
|
+
resolution.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u52A0\u8F7D\u4E2D\u2026" }),
|
|
1952
|
+
resolution.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__error", role: "alert", children: resolution.message }),
|
|
1953
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1446
1954
|
"button",
|
|
1447
1955
|
{
|
|
1448
1956
|
type: "button",
|
|
@@ -1453,22 +1961,13 @@ function ContextSourceList({
|
|
|
1453
1961
|
item.id
|
|
1454
1962
|
))
|
|
1455
1963
|
] }, `${source.trigger}:${source.label}`)),
|
|
1456
|
-
totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ (0,
|
|
1964
|
+
totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u65E0\u5339\u914D\u9879" })
|
|
1457
1965
|
] });
|
|
1458
1966
|
}
|
|
1459
1967
|
|
|
1460
1968
|
// src/view/Composer.tsx
|
|
1461
|
-
var
|
|
1969
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1462
1970
|
var MAX_INPUT_HEIGHT = 200;
|
|
1463
|
-
function formatSize(bytes) {
|
|
1464
|
-
if (bytes < 1024) {
|
|
1465
|
-
return `${bytes} B`;
|
|
1466
|
-
}
|
|
1467
|
-
if (bytes < 1024 * 1024) {
|
|
1468
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1469
|
-
}
|
|
1470
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1471
|
-
}
|
|
1472
1971
|
function detectMention(text, caret) {
|
|
1473
1972
|
const beforeCaret = text.slice(0, caret);
|
|
1474
1973
|
const match = /(?:^|\s)@([^\s@]*)$/.exec(beforeCaret);
|
|
@@ -1497,28 +1996,30 @@ function Composer({
|
|
|
1497
1996
|
contextSources,
|
|
1498
1997
|
contextChips,
|
|
1499
1998
|
onContextChipsChange,
|
|
1500
|
-
callService
|
|
1999
|
+
callService,
|
|
2000
|
+
composerFooter,
|
|
2001
|
+
hideToolbar = false
|
|
1501
2002
|
}) {
|
|
1502
|
-
const [text, setText] = (0,
|
|
1503
|
-
const [dragOver, setDragOver] = (0,
|
|
1504
|
-
const inputRef = (0,
|
|
1505
|
-
const fileInputRef = (0,
|
|
1506
|
-
const plusButtonRef = (0,
|
|
1507
|
-
const composingRef = (0,
|
|
2003
|
+
const [text, setText] = (0, import_react10.useState)("");
|
|
2004
|
+
const [dragOver, setDragOver] = (0, import_react10.useState)(false);
|
|
2005
|
+
const inputRef = (0, import_react10.useRef)(null);
|
|
2006
|
+
const fileInputRef = (0, import_react10.useRef)(null);
|
|
2007
|
+
const plusButtonRef = (0, import_react10.useRef)(null);
|
|
2008
|
+
const composingRef = (0, import_react10.useRef)(false);
|
|
1508
2009
|
const modelChipEnabled = models !== void 0 && models.length > 0;
|
|
1509
|
-
const mentionSources = (0,
|
|
2010
|
+
const mentionSources = (0, import_react10.useMemo)(
|
|
1510
2011
|
() => contextSources?.filter((source) => source.trigger === "@") ?? [],
|
|
1511
2012
|
[contextSources]
|
|
1512
2013
|
);
|
|
1513
|
-
const plusSources = (0,
|
|
2014
|
+
const plusSources = (0, import_react10.useMemo)(
|
|
1514
2015
|
() => contextSources?.filter((source) => source.trigger === "+") ?? [],
|
|
1515
2016
|
[contextSources]
|
|
1516
2017
|
);
|
|
1517
2018
|
const builtinMentionEnabled = onMentionTrigger === void 0 && mentionSources.length > 0;
|
|
1518
2019
|
const builtinPlusEnabled = onPlusMenu === void 0 && plusSources.length > 0;
|
|
1519
|
-
const [mentionState, setMentionState] = (0,
|
|
1520
|
-
const [plusAnchor, setPlusAnchor] = (0,
|
|
1521
|
-
const sourceCacheRef = (0,
|
|
2020
|
+
const [mentionState, setMentionState] = (0, import_react10.useState)(null);
|
|
2021
|
+
const [plusAnchor, setPlusAnchor] = (0, import_react10.useState)(null);
|
|
2022
|
+
const sourceCacheRef = (0, import_react10.useRef)(null);
|
|
1522
2023
|
if (sourceCacheRef.current === null) {
|
|
1523
2024
|
sourceCacheRef.current = /* @__PURE__ */ new Map();
|
|
1524
2025
|
}
|
|
@@ -1537,7 +2038,7 @@ function Composer({
|
|
|
1537
2038
|
setMentionState(null);
|
|
1538
2039
|
setPlusAnchor(null);
|
|
1539
2040
|
};
|
|
1540
|
-
(0,
|
|
2041
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
1541
2042
|
const input = inputRef.current;
|
|
1542
2043
|
if (input) {
|
|
1543
2044
|
input.style.height = "auto";
|
|
@@ -1552,105 +2053,147 @@ function Composer({
|
|
|
1552
2053
|
onSend?.(value);
|
|
1553
2054
|
setText("");
|
|
1554
2055
|
};
|
|
1555
|
-
const
|
|
1556
|
-
|
|
2056
|
+
const sendRef = (0, import_react10.useRef)(send);
|
|
2057
|
+
sendRef.current = send;
|
|
2058
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
2059
|
+
setChatChromeHandlers({ composerSubmit: () => sendRef.current() });
|
|
2060
|
+
}, []);
|
|
2061
|
+
const syncText = (value, caret, rect) => {
|
|
1557
2062
|
setText(value);
|
|
1558
2063
|
if (onMentionTrigger || builtinMentionEnabled) {
|
|
1559
|
-
const caret = event.target.selectionStart ?? value.length;
|
|
1560
2064
|
const query = detectMention(value, caret);
|
|
1561
2065
|
if (onMentionTrigger) {
|
|
1562
2066
|
if (query !== null) {
|
|
1563
|
-
onMentionTrigger(query,
|
|
2067
|
+
onMentionTrigger(query, rect);
|
|
1564
2068
|
}
|
|
1565
2069
|
} else {
|
|
1566
|
-
setMentionState(
|
|
1567
|
-
|
|
1568
|
-
|
|
2070
|
+
setMentionState(query !== null ? { query, anchorRect: rect } : null);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
};
|
|
2074
|
+
const handleChange = (event) => {
|
|
2075
|
+
syncText(
|
|
2076
|
+
event.target.value,
|
|
2077
|
+
event.target.selectionStart ?? event.target.value.length,
|
|
2078
|
+
event.target.getBoundingClientRect()
|
|
2079
|
+
);
|
|
2080
|
+
};
|
|
2081
|
+
const handleBubbleChange = (event) => {
|
|
2082
|
+
const target = event.target;
|
|
2083
|
+
if (!(target instanceof HTMLTextAreaElement)) {
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
syncText(
|
|
2087
|
+
target.value,
|
|
2088
|
+
target.selectionStart ?? target.value.length,
|
|
2089
|
+
target.getBoundingClientRect()
|
|
2090
|
+
);
|
|
2091
|
+
};
|
|
2092
|
+
const handlePasteFiles = (clipboardData) => {
|
|
2093
|
+
const files = Array.from(clipboardData.files);
|
|
2094
|
+
if (files.length > 0 && onAttachFiles) {
|
|
2095
|
+
onAttachFiles(files);
|
|
2096
|
+
return true;
|
|
2097
|
+
}
|
|
2098
|
+
return false;
|
|
2099
|
+
};
|
|
2100
|
+
const dragHandlers = {
|
|
2101
|
+
onDragOver: (event) => {
|
|
2102
|
+
event.preventDefault();
|
|
2103
|
+
setDragOver(true);
|
|
2104
|
+
},
|
|
2105
|
+
onDragLeave: () => setDragOver(false),
|
|
2106
|
+
onDrop: (event) => {
|
|
2107
|
+
event.preventDefault();
|
|
2108
|
+
setDragOver(false);
|
|
2109
|
+
const files = collectDropFiles(event);
|
|
2110
|
+
if (files.length > 0 && onAttachFiles) {
|
|
2111
|
+
onAttachFiles(files);
|
|
1569
2112
|
}
|
|
1570
2113
|
}
|
|
1571
2114
|
};
|
|
1572
|
-
const showToolbar = toolbarStart !== void 0 || toolbarEnd !== void 0 || onPlusMenu !== void 0 || builtinPlusEnabled || onAttachFiles !== void 0 || modelChipEnabled;
|
|
1573
|
-
|
|
2115
|
+
const showToolbar = !hideToolbar && (toolbarStart !== void 0 || toolbarEnd !== void 0 || onPlusMenu !== void 0 || builtinPlusEnabled || onAttachFiles !== void 0 || modelChipEnabled);
|
|
2116
|
+
const fileInputNode = onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2117
|
+
"input",
|
|
2118
|
+
{
|
|
2119
|
+
ref: fileInputRef,
|
|
2120
|
+
type: "file",
|
|
2121
|
+
multiple: true,
|
|
2122
|
+
hidden: true,
|
|
2123
|
+
onChange: (event) => {
|
|
2124
|
+
const files = event.target.files ? Array.from(event.target.files) : [];
|
|
2125
|
+
if (files.length > 0) {
|
|
2126
|
+
onAttachFiles(files);
|
|
2127
|
+
}
|
|
2128
|
+
event.target.value = "";
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
) : null;
|
|
2132
|
+
const popoverNodes = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2133
|
+
builtinMentionEnabled && mentionState && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2134
|
+
AnchoredPopover,
|
|
2135
|
+
{
|
|
2136
|
+
anchorRect: mentionState.anchorRect,
|
|
2137
|
+
onClose: () => setMentionState(null),
|
|
2138
|
+
role: "listbox",
|
|
2139
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2140
|
+
ContextSourceList,
|
|
2141
|
+
{
|
|
2142
|
+
sources: mentionSources,
|
|
2143
|
+
query: mentionState.query,
|
|
2144
|
+
callService,
|
|
2145
|
+
cache: sourceCacheRef.current,
|
|
2146
|
+
onSelect: handleSelectContext
|
|
2147
|
+
}
|
|
2148
|
+
)
|
|
2149
|
+
}
|
|
2150
|
+
),
|
|
2151
|
+
builtinPlusEnabled && plusAnchor && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2152
|
+
AnchoredPopover,
|
|
2153
|
+
{
|
|
2154
|
+
anchorRect: plusAnchor,
|
|
2155
|
+
onClose: () => setPlusAnchor(null),
|
|
2156
|
+
role: "listbox",
|
|
2157
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2158
|
+
ContextSourceList,
|
|
2159
|
+
{
|
|
2160
|
+
sources: plusSources,
|
|
2161
|
+
query: "",
|
|
2162
|
+
callService,
|
|
2163
|
+
cache: sourceCacheRef.current,
|
|
2164
|
+
onSelect: handleSelectContext
|
|
2165
|
+
}
|
|
2166
|
+
)
|
|
2167
|
+
}
|
|
2168
|
+
)
|
|
2169
|
+
] });
|
|
2170
|
+
const fallback = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1574
2171
|
"div",
|
|
1575
2172
|
{
|
|
1576
2173
|
className: `pactor-chat-composer${dragOver ? " pactor-chat-composer--dragover" : ""}`,
|
|
1577
|
-
|
|
1578
|
-
event.preventDefault();
|
|
1579
|
-
setDragOver(true);
|
|
1580
|
-
},
|
|
1581
|
-
onDragLeave: () => setDragOver(false),
|
|
1582
|
-
onDrop: (event) => {
|
|
1583
|
-
event.preventDefault();
|
|
1584
|
-
setDragOver(false);
|
|
1585
|
-
const files = collectDropFiles(event);
|
|
1586
|
-
if (files.length > 0 && onAttachFiles) {
|
|
1587
|
-
onAttachFiles(files);
|
|
1588
|
-
}
|
|
1589
|
-
},
|
|
2174
|
+
...dragHandlers,
|
|
1590
2175
|
children: [
|
|
1591
|
-
attachments !== void 0 &&
|
|
1592
|
-
|
|
1593
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1594
|
-
"div",
|
|
1595
|
-
{
|
|
1596
|
-
className: "pactor-chat-composer__attachment",
|
|
1597
|
-
"data-attachment-id": attachment.id,
|
|
1598
|
-
onClick: () => onAttachmentClick?.(attachment),
|
|
1599
|
-
children: [
|
|
1600
|
-
isImage && attachment.url ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "pactor-chat-composer__attachment-info", children: [
|
|
1601
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.FileText, { size: 14 }),
|
|
1602
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
|
|
1603
|
-
attachment.size !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
|
|
1604
|
-
] }),
|
|
1605
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1606
|
-
"button",
|
|
1607
|
-
{
|
|
1608
|
-
type: "button",
|
|
1609
|
-
className: "pactor-chat-icon-button pactor-chat-composer__attachment-remove",
|
|
1610
|
-
title: "\u79FB\u9664\u9644\u4EF6",
|
|
1611
|
-
"aria-label": "\u79FB\u9664\u9644\u4EF6",
|
|
1612
|
-
onClick: (event) => {
|
|
1613
|
-
event.stopPropagation();
|
|
1614
|
-
onAttachmentsChange?.(
|
|
1615
|
-
attachments.filter((item) => item.id !== attachment.id)
|
|
1616
|
-
);
|
|
1617
|
-
},
|
|
1618
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.X, { size: 12 })
|
|
1619
|
-
}
|
|
1620
|
-
)
|
|
1621
|
-
]
|
|
1622
|
-
},
|
|
1623
|
-
attachment.id
|
|
1624
|
-
);
|
|
1625
|
-
}) }),
|
|
1626
|
-
contextChips !== void 0 && contextChips.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "pactor-chat-composer__contexts", children: contextChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1627
|
-
"span",
|
|
2176
|
+
attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2177
|
+
ComposerAttachments,
|
|
1628
2178
|
{
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
contextChips.filter(
|
|
1642
|
-
(existing) => !(existing.id === chip.id && existing.trigger === chip.trigger)
|
|
1643
|
-
)
|
|
1644
|
-
),
|
|
1645
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.X, { size: 12 })
|
|
1646
|
-
}
|
|
2179
|
+
attachments,
|
|
2180
|
+
onRemove: (id) => onAttachmentsChange?.(attachments.filter((a) => a.id !== id)),
|
|
2181
|
+
onClick: onAttachmentClick
|
|
2182
|
+
}
|
|
2183
|
+
),
|
|
2184
|
+
contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2185
|
+
ComposerContextChips,
|
|
2186
|
+
{
|
|
2187
|
+
chips: contextChips,
|
|
2188
|
+
onRemove: (chip) => onContextChipsChange?.(
|
|
2189
|
+
contextChips.filter(
|
|
2190
|
+
(existing) => !(existing.id === chip.id && existing.trigger === chip.trigger)
|
|
1647
2191
|
)
|
|
1648
|
-
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2192
|
+
)
|
|
2193
|
+
}
|
|
2194
|
+
),
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-composer__row", children: [
|
|
2196
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1654
2197
|
"textarea",
|
|
1655
2198
|
{
|
|
1656
2199
|
ref: inputRef,
|
|
@@ -1667,10 +2210,8 @@ function Composer({
|
|
|
1667
2210
|
composingRef.current = false;
|
|
1668
2211
|
},
|
|
1669
2212
|
onPaste: (event) => {
|
|
1670
|
-
|
|
1671
|
-
if (files.length > 0 && onAttachFiles) {
|
|
2213
|
+
if (handlePasteFiles(event.clipboardData)) {
|
|
1672
2214
|
event.preventDefault();
|
|
1673
|
-
onAttachFiles(files);
|
|
1674
2215
|
}
|
|
1675
2216
|
},
|
|
1676
2217
|
onKeyDown: (event) => {
|
|
@@ -1684,7 +2225,7 @@ function Composer({
|
|
|
1684
2225
|
}
|
|
1685
2226
|
}
|
|
1686
2227
|
),
|
|
1687
|
-
/* @__PURE__ */ (0,
|
|
2228
|
+
hideToolbar ? null : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1688
2229
|
"button",
|
|
1689
2230
|
{
|
|
1690
2231
|
type: "button",
|
|
@@ -1693,14 +2234,14 @@ function Composer({
|
|
|
1693
2234
|
"aria-label": streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
|
|
1694
2235
|
disabled: streaming ? false : disabled || !text.trim(),
|
|
1695
2236
|
onClick: streaming ? onStop : send,
|
|
1696
|
-
children: streaming ? /* @__PURE__ */ (0,
|
|
2237
|
+
children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "arrow-up", size: 16 })
|
|
1697
2238
|
}
|
|
1698
2239
|
)
|
|
1699
2240
|
] }),
|
|
1700
|
-
showToolbar && /* @__PURE__ */ (0,
|
|
2241
|
+
showToolbar && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-composer__toolbar", children: [
|
|
1701
2242
|
toolbarStart,
|
|
1702
|
-
/* @__PURE__ */ (0,
|
|
1703
|
-
(onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ (0,
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "pactor-chat-composer__toolbar-spacer" }),
|
|
2244
|
+
(onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1704
2245
|
"button",
|
|
1705
2246
|
{
|
|
1706
2247
|
ref: plusButtonRef,
|
|
@@ -1716,10 +2257,10 @@ function Composer({
|
|
|
1716
2257
|
setPlusAnchor(rect);
|
|
1717
2258
|
}
|
|
1718
2259
|
},
|
|
1719
|
-
children: /* @__PURE__ */ (0,
|
|
2260
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "plus", size: 14 })
|
|
1720
2261
|
}
|
|
1721
2262
|
),
|
|
1722
|
-
onAttachFiles && /* @__PURE__ */ (0,
|
|
2263
|
+
onAttachFiles && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1723
2264
|
"button",
|
|
1724
2265
|
{
|
|
1725
2266
|
type: "button",
|
|
@@ -1727,11 +2268,11 @@ function Composer({
|
|
|
1727
2268
|
title: "\u6DFB\u52A0\u9644\u4EF6",
|
|
1728
2269
|
"aria-label": "\u6DFB\u52A0\u9644\u4EF6",
|
|
1729
2270
|
onClick: () => fileInputRef.current?.click(),
|
|
1730
|
-
children: /* @__PURE__ */ (0,
|
|
2271
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "paperclip", size: 14 })
|
|
1731
2272
|
}
|
|
1732
2273
|
),
|
|
1733
|
-
modelChipEnabled && /* @__PURE__ */ (0,
|
|
1734
|
-
|
|
2274
|
+
modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2275
|
+
ModelSelect,
|
|
1735
2276
|
{
|
|
1736
2277
|
models,
|
|
1737
2278
|
model,
|
|
@@ -1740,104 +2281,206 @@ function Composer({
|
|
|
1740
2281
|
),
|
|
1741
2282
|
toolbarEnd
|
|
1742
2283
|
] }),
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
ref: fileInputRef,
|
|
1747
|
-
type: "file",
|
|
1748
|
-
multiple: true,
|
|
1749
|
-
hidden: true,
|
|
1750
|
-
onChange: (event) => {
|
|
1751
|
-
const files = event.target.files ? Array.from(event.target.files) : [];
|
|
1752
|
-
if (files.length > 0) {
|
|
1753
|
-
onAttachFiles(files);
|
|
1754
|
-
}
|
|
1755
|
-
event.target.value = "";
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
),
|
|
1759
|
-
builtinMentionEnabled && mentionState && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1760
|
-
AnchoredPopover,
|
|
1761
|
-
{
|
|
1762
|
-
anchorRect: mentionState.anchorRect,
|
|
1763
|
-
onClose: () => setMentionState(null),
|
|
1764
|
-
role: "listbox",
|
|
1765
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1766
|
-
ContextSourceList,
|
|
1767
|
-
{
|
|
1768
|
-
sources: mentionSources,
|
|
1769
|
-
query: mentionState.query,
|
|
1770
|
-
callService,
|
|
1771
|
-
cache: sourceCacheRef.current,
|
|
1772
|
-
onSelect: handleSelectContext
|
|
1773
|
-
}
|
|
1774
|
-
)
|
|
1775
|
-
}
|
|
1776
|
-
),
|
|
1777
|
-
builtinPlusEnabled && plusAnchor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1778
|
-
AnchoredPopover,
|
|
1779
|
-
{
|
|
1780
|
-
anchorRect: plusAnchor,
|
|
1781
|
-
onClose: () => setPlusAnchor(null),
|
|
1782
|
-
role: "listbox",
|
|
1783
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1784
|
-
ContextSourceList,
|
|
1785
|
-
{
|
|
1786
|
-
sources: plusSources,
|
|
1787
|
-
query: "",
|
|
1788
|
-
callService,
|
|
1789
|
-
cache: sourceCacheRef.current,
|
|
1790
|
-
onSelect: handleSelectContext
|
|
1791
|
-
}
|
|
1792
|
-
)
|
|
1793
|
-
}
|
|
1794
|
-
)
|
|
2284
|
+
composerFooter !== void 0 && composerFooter !== null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-composer__footer", children: composerFooter }) : null,
|
|
2285
|
+
fileInputNode,
|
|
2286
|
+
popoverNodes
|
|
1795
2287
|
]
|
|
1796
2288
|
}
|
|
1797
2289
|
);
|
|
2290
|
+
const bridge = {
|
|
2291
|
+
text,
|
|
2292
|
+
streaming,
|
|
2293
|
+
disabled,
|
|
2294
|
+
attachments,
|
|
2295
|
+
contextChips,
|
|
2296
|
+
toolbarStart,
|
|
2297
|
+
toolbarEnd,
|
|
2298
|
+
composerFooter,
|
|
2299
|
+
models,
|
|
2300
|
+
model,
|
|
2301
|
+
showPlus: onPlusMenu !== void 0 || builtinPlusEnabled,
|
|
2302
|
+
showAttach: onAttachFiles !== void 0,
|
|
2303
|
+
modelChipEnabled,
|
|
2304
|
+
send,
|
|
2305
|
+
stop: onStop,
|
|
2306
|
+
openFilePicker: () => fileInputRef.current?.click(),
|
|
2307
|
+
plusClick: (rect) => {
|
|
2308
|
+
if (onPlusMenu) {
|
|
2309
|
+
onPlusMenu(rect);
|
|
2310
|
+
} else {
|
|
2311
|
+
setPlusAnchor(rect);
|
|
2312
|
+
}
|
|
2313
|
+
},
|
|
2314
|
+
removeAttachment: (id) => onAttachmentsChange?.((attachments ?? []).filter((a) => a.id !== id)),
|
|
2315
|
+
attachmentClick: onAttachmentClick,
|
|
2316
|
+
removeChip: (chip) => onContextChipsChange?.(
|
|
2317
|
+
(contextChips ?? []).filter(
|
|
2318
|
+
(existing) => !(existing.id === chip.id && existing.trigger === chip.trigger)
|
|
2319
|
+
)
|
|
2320
|
+
),
|
|
2321
|
+
modelChange: onModelChange
|
|
2322
|
+
};
|
|
2323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2324
|
+
ChromeSlot,
|
|
2325
|
+
{
|
|
2326
|
+
fragment: buildComposerFragment({
|
|
2327
|
+
placeholder,
|
|
2328
|
+
disabled,
|
|
2329
|
+
hasFooter: composerFooter !== void 0 && composerFooter !== null,
|
|
2330
|
+
hideToolbar
|
|
2331
|
+
}),
|
|
2332
|
+
components: COMPOSER_INTERNAL_COMPONENTS,
|
|
2333
|
+
fallback,
|
|
2334
|
+
wrap: (children) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ComposerBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2335
|
+
"div",
|
|
2336
|
+
{
|
|
2337
|
+
className: `pactor-chat-composer pactor-chat-composer--dsl${dragOver ? " pactor-chat-composer--dragover" : ""}`,
|
|
2338
|
+
...dragHandlers,
|
|
2339
|
+
onChange: handleBubbleChange,
|
|
2340
|
+
onPaste: (event) => {
|
|
2341
|
+
if (handlePasteFiles(event.clipboardData)) {
|
|
2342
|
+
event.preventDefault();
|
|
2343
|
+
}
|
|
2344
|
+
},
|
|
2345
|
+
children: [
|
|
2346
|
+
children,
|
|
2347
|
+
fileInputNode,
|
|
2348
|
+
popoverNodes
|
|
2349
|
+
]
|
|
2350
|
+
}
|
|
2351
|
+
) })
|
|
2352
|
+
}
|
|
2353
|
+
);
|
|
1798
2354
|
}
|
|
1799
2355
|
|
|
1800
|
-
// src/view/
|
|
1801
|
-
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1802
|
-
var DEFAULT_CHAT_GREETING = "\u4F60\u597D\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F";
|
|
2356
|
+
// src/view/chrome/empty-state.tsx
|
|
1803
2357
|
function suggestionLabel(suggestion) {
|
|
1804
2358
|
return typeof suggestion === "string" ? suggestion : suggestion.label;
|
|
1805
2359
|
}
|
|
1806
2360
|
function suggestionPrompt(suggestion) {
|
|
1807
2361
|
return typeof suggestion === "string" ? suggestion : suggestion.prompt ?? suggestion.label;
|
|
1808
2362
|
}
|
|
1809
|
-
function
|
|
1810
|
-
|
|
2363
|
+
function buildEmptyStateFragment(props) {
|
|
2364
|
+
const children = [
|
|
2365
|
+
{
|
|
2366
|
+
type: "Typography",
|
|
2367
|
+
props: {
|
|
2368
|
+
variant: "h3",
|
|
2369
|
+
text: props.greeting,
|
|
2370
|
+
className: "pactor-chat-empty__greeting"
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
];
|
|
2374
|
+
if (props.subtitle) {
|
|
2375
|
+
children.push({
|
|
2376
|
+
type: "Text",
|
|
2377
|
+
props: {
|
|
2378
|
+
type: "secondary",
|
|
2379
|
+
text: props.subtitle,
|
|
2380
|
+
className: "pactor-chat-empty__subtitle"
|
|
2381
|
+
}
|
|
2382
|
+
});
|
|
2383
|
+
}
|
|
2384
|
+
if (props.suggestions && props.suggestions.length > 0) {
|
|
2385
|
+
children.push({
|
|
2386
|
+
type: "Flex",
|
|
2387
|
+
props: {
|
|
2388
|
+
gap: "small",
|
|
2389
|
+
justify: "center",
|
|
2390
|
+
className: "pactor-chat-empty__suggestions"
|
|
2391
|
+
},
|
|
2392
|
+
children: props.suggestions.map((suggestion) => ({
|
|
2393
|
+
type: "Button",
|
|
2394
|
+
props: {
|
|
2395
|
+
text: suggestionLabel(suggestion),
|
|
2396
|
+
variant: "default",
|
|
2397
|
+
size: "middle",
|
|
2398
|
+
className: "pactor-chat-empty__suggestion"
|
|
2399
|
+
},
|
|
2400
|
+
events: {
|
|
2401
|
+
onClick: [
|
|
2402
|
+
{
|
|
2403
|
+
action: "chat.sendSuggestion",
|
|
2404
|
+
params: { text: suggestionPrompt(suggestion) }
|
|
2405
|
+
}
|
|
2406
|
+
]
|
|
2407
|
+
}
|
|
2408
|
+
}))
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
return {
|
|
2412
|
+
requires: ["Flex", "Typography", "Text", "Button"],
|
|
2413
|
+
node: {
|
|
2414
|
+
type: "Flex",
|
|
2415
|
+
props: { direction: "vertical", align: "center", gap: "middle" },
|
|
2416
|
+
children
|
|
2417
|
+
}
|
|
2418
|
+
};
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
// src/view/EmptyState.tsx
|
|
2422
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2423
|
+
var DEFAULT_CHAT_GREETING = "\u4F60\u597D\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F";
|
|
2424
|
+
function suggestionLabel2(suggestion) {
|
|
2425
|
+
return typeof suggestion === "string" ? suggestion : suggestion.label;
|
|
2426
|
+
}
|
|
2427
|
+
function suggestionPrompt2(suggestion) {
|
|
2428
|
+
return typeof suggestion === "string" ? suggestion : suggestion.prompt ?? suggestion.label;
|
|
2429
|
+
}
|
|
2430
|
+
function EmptyStateFallback({
|
|
1811
2431
|
subtitle,
|
|
1812
2432
|
suggestions,
|
|
1813
|
-
onSuggestionClick
|
|
2433
|
+
onSuggestionClick,
|
|
2434
|
+
greeting
|
|
1814
2435
|
}) {
|
|
1815
|
-
return /* @__PURE__ */ (0,
|
|
1816
|
-
/* @__PURE__ */ (0,
|
|
1817
|
-
subtitle && /* @__PURE__ */ (0,
|
|
1818
|
-
suggestions && suggestions.length > 0 && /* @__PURE__ */ (0,
|
|
2436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2437
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__greeting", children: greeting }),
|
|
2438
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__subtitle", children: subtitle }),
|
|
2439
|
+
suggestions && suggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__suggestions", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1819
2440
|
"button",
|
|
1820
2441
|
{
|
|
1821
2442
|
type: "button",
|
|
1822
2443
|
className: "pactor-chat-empty__suggestion",
|
|
1823
|
-
onClick: () => onSuggestionClick?.(
|
|
1824
|
-
children:
|
|
2444
|
+
onClick: () => onSuggestionClick?.(suggestionPrompt2(suggestion)),
|
|
2445
|
+
children: suggestionLabel2(suggestion)
|
|
1825
2446
|
},
|
|
1826
|
-
|
|
2447
|
+
suggestionLabel2(suggestion)
|
|
1827
2448
|
)) })
|
|
1828
2449
|
] });
|
|
1829
2450
|
}
|
|
2451
|
+
function EmptyState({
|
|
2452
|
+
greeting = DEFAULT_CHAT_GREETING,
|
|
2453
|
+
subtitle,
|
|
2454
|
+
suggestions,
|
|
2455
|
+
onSuggestionClick
|
|
2456
|
+
}) {
|
|
2457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2458
|
+
ChromeSlot,
|
|
2459
|
+
{
|
|
2460
|
+
fragment: buildEmptyStateFragment({ greeting, subtitle, suggestions }),
|
|
2461
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2462
|
+
EmptyStateFallback,
|
|
2463
|
+
{
|
|
2464
|
+
greeting,
|
|
2465
|
+
subtitle,
|
|
2466
|
+
suggestions,
|
|
2467
|
+
onSuggestionClick
|
|
2468
|
+
}
|
|
2469
|
+
)
|
|
2470
|
+
}
|
|
2471
|
+
) });
|
|
2472
|
+
}
|
|
1830
2473
|
|
|
1831
2474
|
// src/view/MessageBubble.tsx
|
|
1832
|
-
var
|
|
2475
|
+
var import_react13 = require("react");
|
|
1833
2476
|
|
|
1834
2477
|
// src/view/ActivityTrace.tsx
|
|
1835
|
-
var
|
|
2478
|
+
var import_components8 = require("@pactor-app/ui/components");
|
|
1836
2479
|
var import_markdown3 = require("@pactor-app/markdown");
|
|
1837
|
-
var
|
|
1838
|
-
var
|
|
2480
|
+
var import_react11 = require("react");
|
|
2481
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1839
2482
|
function usePinnedCollapse(autoOpen) {
|
|
1840
|
-
const [state, setState] = (0,
|
|
2483
|
+
const [state, setState] = (0, import_react11.useState)("auto");
|
|
1841
2484
|
const open = state === "auto" ? autoOpen : state === "pinned-open";
|
|
1842
2485
|
const toggle = () => {
|
|
1843
2486
|
setState(open ? "pinned-closed" : "pinned-open");
|
|
@@ -1863,8 +2506,8 @@ function statusText(message, mode, toolCount) {
|
|
|
1863
2506
|
}
|
|
1864
2507
|
function useElapsedSeconds(startedAt, active) {
|
|
1865
2508
|
const compute = () => Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
|
|
1866
|
-
const [elapsed, setElapsed] = (0,
|
|
1867
|
-
(0,
|
|
2509
|
+
const [elapsed, setElapsed] = (0, import_react11.useState)(compute);
|
|
2510
|
+
(0, import_react11.useEffect)(() => {
|
|
1868
2511
|
if (!active) {
|
|
1869
2512
|
setElapsed(compute());
|
|
1870
2513
|
return;
|
|
@@ -1878,15 +2521,15 @@ function useElapsedSeconds(startedAt, active) {
|
|
|
1878
2521
|
}
|
|
1879
2522
|
function TraceStatusIcon({ status }) {
|
|
1880
2523
|
if (status === "running") {
|
|
1881
|
-
return /* @__PURE__ */ (0,
|
|
2524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" });
|
|
1882
2525
|
}
|
|
1883
2526
|
if (status === "success") {
|
|
1884
|
-
return /* @__PURE__ */ (0,
|
|
2527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "check-circle", size: 13 });
|
|
1885
2528
|
}
|
|
1886
2529
|
if (status === "failed") {
|
|
1887
|
-
return /* @__PURE__ */ (0,
|
|
2530
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "x-circle", size: 13 });
|
|
1888
2531
|
}
|
|
1889
|
-
return /* @__PURE__ */ (0,
|
|
2532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "clock", size: 13 });
|
|
1890
2533
|
}
|
|
1891
2534
|
function summarizeArgs(args) {
|
|
1892
2535
|
if (args === void 0) {
|
|
@@ -1915,16 +2558,16 @@ function formatDetail(value) {
|
|
|
1915
2558
|
}
|
|
1916
2559
|
}
|
|
1917
2560
|
function TraceRow({ entry }) {
|
|
1918
|
-
const [open, setOpen] = (0,
|
|
2561
|
+
const [open, setOpen] = (0, import_react11.useState)(false);
|
|
1919
2562
|
const summary = summarizeArgs(entry.args);
|
|
1920
|
-
return /* @__PURE__ */ (0,
|
|
2563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1921
2564
|
"div",
|
|
1922
2565
|
{
|
|
1923
2566
|
className: "pactor-chat-trace__entry",
|
|
1924
2567
|
"data-status": entry.status,
|
|
1925
2568
|
"data-open": open,
|
|
1926
2569
|
children: [
|
|
1927
|
-
/* @__PURE__ */ (0,
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1928
2571
|
"button",
|
|
1929
2572
|
{
|
|
1930
2573
|
type: "button",
|
|
@@ -1932,16 +2575,16 @@ function TraceRow({ entry }) {
|
|
|
1932
2575
|
"aria-expanded": open,
|
|
1933
2576
|
onClick: () => setOpen((value) => !value),
|
|
1934
2577
|
children: [
|
|
1935
|
-
/* @__PURE__ */ (0,
|
|
1936
|
-
/* @__PURE__ */ (0,
|
|
1937
|
-
/* @__PURE__ */ (0,
|
|
1938
|
-
summary && /* @__PURE__ */ (0,
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) }),
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TraceStatusIcon, { status: entry.status }) }),
|
|
2580
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-title", children: entry.title ?? entry.name }),
|
|
2581
|
+
summary && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-args", children: summary })
|
|
1939
2582
|
]
|
|
1940
2583
|
}
|
|
1941
2584
|
),
|
|
1942
|
-
open && /* @__PURE__ */ (0,
|
|
1943
|
-
entry.args !== void 0 && /* @__PURE__ */ (0,
|
|
1944
|
-
/* @__PURE__ */ (0,
|
|
2585
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "pactor-chat-trace__entry-body", children: [
|
|
2586
|
+
entry.args !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: formatDetail(entry.args) }),
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: entry.status === "failed" ? entry.error ?? "\u6267\u884C\u5931\u8D25" : formatDetail(entry.result) })
|
|
1945
2588
|
] })
|
|
1946
2589
|
]
|
|
1947
2590
|
}
|
|
@@ -1953,14 +2596,14 @@ function ThinkingCard({
|
|
|
1953
2596
|
}) {
|
|
1954
2597
|
const partStreaming = part.status === "streaming";
|
|
1955
2598
|
const { open, toggle } = usePinnedCollapse(partStreaming && !answerPhase);
|
|
1956
|
-
return /* @__PURE__ */ (0,
|
|
2599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1957
2600
|
"div",
|
|
1958
2601
|
{
|
|
1959
2602
|
className: "pactor-chat-thinking",
|
|
1960
2603
|
"data-open": open,
|
|
1961
2604
|
"data-streaming": partStreaming,
|
|
1962
2605
|
children: [
|
|
1963
|
-
/* @__PURE__ */ (0,
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1964
2607
|
"button",
|
|
1965
2608
|
{
|
|
1966
2609
|
type: "button",
|
|
@@ -1968,13 +2611,13 @@ function ThinkingCard({
|
|
|
1968
2611
|
"aria-expanded": open,
|
|
1969
2612
|
onClick: toggle,
|
|
1970
2613
|
children: [
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
1973
|
-
/* @__PURE__ */ (0,
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) }),
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-thinking__icon", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "brain", size: 13 }) }),
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u601D\u8003\u8FC7\u7A0B" })
|
|
1974
2617
|
]
|
|
1975
2618
|
}
|
|
1976
2619
|
),
|
|
1977
|
-
open && /* @__PURE__ */ (0,
|
|
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 }) })
|
|
1978
2621
|
]
|
|
1979
2622
|
}
|
|
1980
2623
|
);
|
|
@@ -1988,7 +2631,7 @@ function ActivityTrace({ message }) {
|
|
|
1988
2631
|
);
|
|
1989
2632
|
const answerPhase = mode === "responding" || !streaming;
|
|
1990
2633
|
const { open, toggle } = usePinnedCollapse(!answerPhase);
|
|
1991
|
-
const mountTimeRef = (0,
|
|
2634
|
+
const mountTimeRef = (0, import_react11.useRef)(0);
|
|
1992
2635
|
if (mountTimeRef.current === 0) {
|
|
1993
2636
|
mountTimeRef.current = Date.now();
|
|
1994
2637
|
}
|
|
@@ -1996,23 +2639,23 @@ function ActivityTrace({ message }) {
|
|
|
1996
2639
|
message.createdAt ?? mountTimeRef.current,
|
|
1997
2640
|
streaming
|
|
1998
2641
|
);
|
|
1999
|
-
const header = /* @__PURE__ */ (0,
|
|
2000
|
-
/* @__PURE__ */ (0,
|
|
2001
|
-
/* @__PURE__ */ (0,
|
|
2642
|
+
const header = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__status-icon", children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "check-circle", size: 13 }) }),
|
|
2644
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2002
2645
|
"span",
|
|
2003
2646
|
{
|
|
2004
2647
|
className: `pactor-chat-trace__status-text${streaming ? " pactor-chat-trace__status-text--breathing" : ""}`,
|
|
2005
2648
|
children: statusText(message, mode, entries.length)
|
|
2006
2649
|
}
|
|
2007
2650
|
),
|
|
2008
|
-
/* @__PURE__ */ (0,
|
|
2651
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "pactor-chat-trace__elapsed", children: [
|
|
2009
2652
|
elapsed,
|
|
2010
2653
|
"s"
|
|
2011
2654
|
] }),
|
|
2012
|
-
entries.length > 0 && /* @__PURE__ */ (0,
|
|
2655
|
+
entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) })
|
|
2013
2656
|
] });
|
|
2014
|
-
return /* @__PURE__ */ (0,
|
|
2015
|
-
entries.length > 0 ? /* @__PURE__ */ (0,
|
|
2657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "pactor-chat-trace", "data-open": open, children: [
|
|
2658
|
+
entries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2016
2659
|
"button",
|
|
2017
2660
|
{
|
|
2018
2661
|
type: "button",
|
|
@@ -2021,8 +2664,8 @@ function ActivityTrace({ message }) {
|
|
|
2021
2664
|
onClick: toggle,
|
|
2022
2665
|
children: header
|
|
2023
2666
|
}
|
|
2024
|
-
) : /* @__PURE__ */ (0,
|
|
2025
|
-
thinkingParts.map((part, index) => /* @__PURE__ */ (0,
|
|
2667
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-trace__header", children: header }),
|
|
2668
|
+
thinkingParts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2026
2669
|
ThinkingCard,
|
|
2027
2670
|
{
|
|
2028
2671
|
part,
|
|
@@ -2030,25 +2673,66 @@ function ActivityTrace({ message }) {
|
|
|
2030
2673
|
},
|
|
2031
2674
|
part.id ?? index
|
|
2032
2675
|
)),
|
|
2033
|
-
open && entries.length > 0 && /* @__PURE__ */ (0,
|
|
2676
|
+
open && entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-trace__entries", children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TraceRow, { entry }, entry.callIndex)) })
|
|
2034
2677
|
] });
|
|
2035
2678
|
}
|
|
2036
2679
|
|
|
2037
2680
|
// src/view/MessageActions.tsx
|
|
2038
|
-
var
|
|
2039
|
-
var
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2681
|
+
var import_components9 = require("@pactor-app/ui/components");
|
|
2682
|
+
var import_react12 = require("react");
|
|
2683
|
+
|
|
2684
|
+
// src/view/chrome/message-actions.tsx
|
|
2685
|
+
function buildMessageActionsFragment(args) {
|
|
2686
|
+
const { actions, copied, token } = args;
|
|
2687
|
+
return {
|
|
2688
|
+
requires: ["Flex", "Tooltip", "Button", "Icon"],
|
|
2689
|
+
node: {
|
|
2690
|
+
type: "Flex",
|
|
2691
|
+
props: { gap: "small" },
|
|
2692
|
+
children: actions.map((action) => {
|
|
2693
|
+
const copiedFeedback = action.builtin === "copy" && copied;
|
|
2694
|
+
const label = copiedFeedback ? "\u5DF2\u590D\u5236" : action.label;
|
|
2695
|
+
const iconName = copiedFeedback ? "check" : action.icon;
|
|
2696
|
+
return {
|
|
2697
|
+
type: "Tooltip",
|
|
2698
|
+
props: { content: label },
|
|
2699
|
+
children: [
|
|
2700
|
+
{
|
|
2701
|
+
type: "Button",
|
|
2702
|
+
props: {
|
|
2703
|
+
variant: "text",
|
|
2704
|
+
size: "small",
|
|
2705
|
+
className: "pactor-chat-icon-button"
|
|
2706
|
+
},
|
|
2707
|
+
events: {
|
|
2708
|
+
onClick: [
|
|
2709
|
+
{
|
|
2710
|
+
action: "chat.messageAction",
|
|
2711
|
+
params: { token, actionId: action.id }
|
|
2712
|
+
}
|
|
2713
|
+
]
|
|
2714
|
+
},
|
|
2715
|
+
children: [
|
|
2716
|
+
{
|
|
2717
|
+
type: "Icon",
|
|
2718
|
+
props: {
|
|
2719
|
+
// 契约图标名直通 ui Icon 白名单(spec: chat-icon-convergence;
|
|
2720
|
+
// 未知名由 ui Icon 渲染占位)
|
|
2721
|
+
name: iconName ?? "help-circle",
|
|
2722
|
+
size: 14
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
]
|
|
2726
|
+
}
|
|
2727
|
+
]
|
|
2728
|
+
};
|
|
2729
|
+
})
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
// src/view/MessageActions.tsx
|
|
2735
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2052
2736
|
var BUILTIN_ACTION_DEFAULTS = {
|
|
2053
2737
|
copy: {
|
|
2054
2738
|
label: "\u590D\u5236",
|
|
@@ -2121,7 +2805,21 @@ function MessageActions({
|
|
|
2121
2805
|
callService,
|
|
2122
2806
|
onMessageAction
|
|
2123
2807
|
}) {
|
|
2124
|
-
const [copied, setCopied] = (0,
|
|
2808
|
+
const [copied, setCopied] = (0, import_react12.useState)(false);
|
|
2809
|
+
const dispatchRef = (0, import_react12.useRef)(
|
|
2810
|
+
() => {
|
|
2811
|
+
}
|
|
2812
|
+
);
|
|
2813
|
+
const visibleActionsRef = (0, import_react12.useRef)([]);
|
|
2814
|
+
(0, import_react12.useEffect)(() => {
|
|
2815
|
+
setMessageActionDispatcher(message.id, (actionId) => {
|
|
2816
|
+
const action = visibleActionsRef.current.find((a) => a.id === actionId);
|
|
2817
|
+
if (action) {
|
|
2818
|
+
dispatchRef.current(action);
|
|
2819
|
+
}
|
|
2820
|
+
});
|
|
2821
|
+
return () => clearMessageActionDispatcher(message.id);
|
|
2822
|
+
}, [message.id]);
|
|
2125
2823
|
const copy = async () => {
|
|
2126
2824
|
try {
|
|
2127
2825
|
await navigator.clipboard.writeText(collectMessageText(message));
|
|
@@ -2181,41 +2879,53 @@ function MessageActions({
|
|
|
2181
2879
|
}
|
|
2182
2880
|
onMessageAction?.(action.id, message);
|
|
2183
2881
|
};
|
|
2184
|
-
|
|
2882
|
+
dispatchRef.current = dispatch;
|
|
2883
|
+
visibleActionsRef.current = visibleActions;
|
|
2884
|
+
const buttons = visibleActions.map((action) => {
|
|
2885
|
+
const copiedFeedback = action.builtin === "copy" && copied;
|
|
2886
|
+
const label = copiedFeedback ? "\u5DF2\u590D\u5236" : action.label;
|
|
2887
|
+
const iconName = copiedFeedback ? "check" : action.icon;
|
|
2888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2889
|
+
"button",
|
|
2890
|
+
{
|
|
2891
|
+
type: "button",
|
|
2892
|
+
className: "pactor-chat-icon-button",
|
|
2893
|
+
title: label,
|
|
2894
|
+
"aria-label": label,
|
|
2895
|
+
"data-message-action": action.id,
|
|
2896
|
+
onClick: () => dispatch(action),
|
|
2897
|
+
children: iconName !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: iconName, size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "help-circle", size: 14 })
|
|
2898
|
+
},
|
|
2899
|
+
action.id
|
|
2900
|
+
);
|
|
2901
|
+
});
|
|
2902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2185
2903
|
"div",
|
|
2186
2904
|
{
|
|
2187
2905
|
className: `pactor-chat-message__actions${forceVisible ? " pactor-chat-message__actions--visible" : ""}`,
|
|
2188
|
-
children:
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
"aria-label": label,
|
|
2200
|
-
"data-message-action": action.id,
|
|
2201
|
-
onClick: () => dispatch(action),
|
|
2202
|
-
children: Icon ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.HelpCircle, { size: 14, "data-icon-placeholder": "true" })
|
|
2203
|
-
},
|
|
2204
|
-
action.id
|
|
2205
|
-
);
|
|
2206
|
-
})
|
|
2906
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2907
|
+
ChromeSlot,
|
|
2908
|
+
{
|
|
2909
|
+
fragment: buildMessageActionsFragment({
|
|
2910
|
+
actions: visibleActions,
|
|
2911
|
+
copied,
|
|
2912
|
+
token: message.id
|
|
2913
|
+
}),
|
|
2914
|
+
fallback: buttons
|
|
2915
|
+
}
|
|
2916
|
+
)
|
|
2207
2917
|
}
|
|
2208
2918
|
);
|
|
2209
2919
|
}
|
|
2210
2920
|
|
|
2211
2921
|
// src/view/MessageBubble.tsx
|
|
2212
|
-
var
|
|
2922
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2213
2923
|
function MessageEditForm({
|
|
2214
2924
|
initialText,
|
|
2215
2925
|
onConfirm,
|
|
2216
2926
|
onCancel
|
|
2217
2927
|
}) {
|
|
2218
|
-
const [text, setText] = (0,
|
|
2928
|
+
const [text, setText] = (0, import_react13.useState)(initialText);
|
|
2219
2929
|
const confirm = () => {
|
|
2220
2930
|
const value = text.trim();
|
|
2221
2931
|
if (!value) {
|
|
@@ -2223,8 +2933,8 @@ function MessageEditForm({
|
|
|
2223
2933
|
}
|
|
2224
2934
|
onConfirm(value);
|
|
2225
2935
|
};
|
|
2226
|
-
return /* @__PURE__ */ (0,
|
|
2227
|
-
/* @__PURE__ */ (0,
|
|
2936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__edit", children: [
|
|
2937
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2228
2938
|
"textarea",
|
|
2229
2939
|
{
|
|
2230
2940
|
className: "pactor-chat-message__edit-input",
|
|
@@ -2242,8 +2952,8 @@ function MessageEditForm({
|
|
|
2242
2952
|
}
|
|
2243
2953
|
}
|
|
2244
2954
|
),
|
|
2245
|
-
/* @__PURE__ */ (0,
|
|
2246
|
-
/* @__PURE__ */ (0,
|
|
2955
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__edit-actions", children: [
|
|
2956
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2247
2957
|
"button",
|
|
2248
2958
|
{
|
|
2249
2959
|
type: "button",
|
|
@@ -2253,7 +2963,7 @@ function MessageEditForm({
|
|
|
2253
2963
|
children: "\u53D1\u9001"
|
|
2254
2964
|
}
|
|
2255
2965
|
),
|
|
2256
|
-
/* @__PURE__ */ (0,
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2257
2967
|
"button",
|
|
2258
2968
|
{
|
|
2259
2969
|
type: "button",
|
|
@@ -2279,7 +2989,7 @@ function MessageBubble({
|
|
|
2279
2989
|
onMessageAction,
|
|
2280
2990
|
onOpenArtifact
|
|
2281
2991
|
}) {
|
|
2282
|
-
const [editing, setEditing] = (0,
|
|
2992
|
+
const [editing, setEditing] = (0, import_react13.useState)(false);
|
|
2283
2993
|
const bubbleScope = {
|
|
2284
2994
|
conversation: scope?.conversation ?? {},
|
|
2285
2995
|
message: { id: message.id },
|
|
@@ -2287,21 +2997,21 @@ function MessageBubble({
|
|
|
2287
2997
|
};
|
|
2288
2998
|
const streaming = message.status === "streaming";
|
|
2289
2999
|
const live = message.status === "pending" || message.status === "streaming";
|
|
2290
|
-
const wasLiveRef = (0,
|
|
3000
|
+
const wasLiveRef = (0, import_react13.useRef)(live);
|
|
2291
3001
|
if (live) {
|
|
2292
3002
|
wasLiveRef.current = true;
|
|
2293
3003
|
}
|
|
2294
3004
|
const showTrace = message.role === "assistant" && (wasLiveRef.current || message.parts.some(
|
|
2295
3005
|
(part) => part.type === "thinking" || part.type === "tool-call" || part.type === "tool-result"
|
|
2296
3006
|
));
|
|
2297
|
-
return /* @__PURE__ */ (0,
|
|
3007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2298
3008
|
"div",
|
|
2299
3009
|
{
|
|
2300
3010
|
className: `pactor-chat-message pactor-chat-message--${message.role}`,
|
|
2301
3011
|
"data-message-id": message.id,
|
|
2302
3012
|
"data-message-status": message.status,
|
|
2303
3013
|
children: [
|
|
2304
|
-
editing ? /* @__PURE__ */ (0,
|
|
3014
|
+
editing ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2305
3015
|
MessageEditForm,
|
|
2306
3016
|
{
|
|
2307
3017
|
initialText: collectMessageText(message),
|
|
@@ -2311,9 +3021,9 @@ function MessageBubble({
|
|
|
2311
3021
|
},
|
|
2312
3022
|
onCancel: () => setEditing(false)
|
|
2313
3023
|
}
|
|
2314
|
-
) : /* @__PURE__ */ (0,
|
|
2315
|
-
showTrace && /* @__PURE__ */ (0,
|
|
2316
|
-
message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ (0,
|
|
3024
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__body", children: [
|
|
3025
|
+
showTrace && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ActivityTrace, { message }),
|
|
3026
|
+
message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "pactor-chat-message__pending", children: "\u2026" }) : message.parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2317
3027
|
PartRenderer,
|
|
2318
3028
|
{
|
|
2319
3029
|
part,
|
|
@@ -2325,7 +3035,7 @@ function MessageBubble({
|
|
|
2325
3035
|
part.id ?? index
|
|
2326
3036
|
))
|
|
2327
3037
|
] }),
|
|
2328
|
-
!editing && /* @__PURE__ */ (0,
|
|
3038
|
+
!editing && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2329
3039
|
MessageActions,
|
|
2330
3040
|
{
|
|
2331
3041
|
message,
|
|
@@ -2345,7 +3055,7 @@ function MessageBubble({
|
|
|
2345
3055
|
}
|
|
2346
3056
|
|
|
2347
3057
|
// src/view/ChatView.tsx
|
|
2348
|
-
var
|
|
3058
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2349
3059
|
function lastContentLength(messages) {
|
|
2350
3060
|
const last = messages[messages.length - 1];
|
|
2351
3061
|
if (!last) {
|
|
@@ -2379,6 +3089,8 @@ function ChatView({
|
|
|
2379
3089
|
onAttachmentClick,
|
|
2380
3090
|
toolbarStart,
|
|
2381
3091
|
toolbarEnd,
|
|
3092
|
+
composerFooter,
|
|
3093
|
+
hideToolbar,
|
|
2382
3094
|
onMentionTrigger,
|
|
2383
3095
|
onPlusMenu,
|
|
2384
3096
|
models,
|
|
@@ -2389,16 +3101,17 @@ function ChatView({
|
|
|
2389
3101
|
onContextsChange,
|
|
2390
3102
|
callService,
|
|
2391
3103
|
messageActions,
|
|
2392
|
-
onMessageAction
|
|
3104
|
+
onMessageAction,
|
|
3105
|
+
composerBottom
|
|
2393
3106
|
}) {
|
|
2394
|
-
const messages = (0,
|
|
3107
|
+
const messages = (0, import_react14.useSyncExternalStore)(
|
|
2395
3108
|
(listener) => store.subscribe(listener),
|
|
2396
3109
|
() => store.getMessages()
|
|
2397
3110
|
);
|
|
2398
3111
|
const isStreaming = messages.some(
|
|
2399
3112
|
(message) => message.status === "pending" || message.status === "streaming"
|
|
2400
3113
|
);
|
|
2401
|
-
const runtime = (0,
|
|
3114
|
+
const runtime = (0, import_react14.useMemo)(() => {
|
|
2402
3115
|
if (!safeRegistry) {
|
|
2403
3116
|
return void 0;
|
|
2404
3117
|
}
|
|
@@ -2415,12 +3128,12 @@ function ChatView({
|
|
|
2415
3128
|
user
|
|
2416
3129
|
});
|
|
2417
3130
|
}, [safeRegistry, capabilities, permission, confirm, user]);
|
|
2418
|
-
const scope = (0,
|
|
3131
|
+
const scope = (0, import_react14.useMemo)(
|
|
2419
3132
|
() => ({ conversation: { id: conversationId }, params }),
|
|
2420
3133
|
[conversationId, params]
|
|
2421
3134
|
);
|
|
2422
|
-
const notifiedArtifactsRef = (0,
|
|
2423
|
-
(0,
|
|
3135
|
+
const notifiedArtifactsRef = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
|
|
3136
|
+
(0, import_react14.useEffect)(() => {
|
|
2424
3137
|
if (!onArtifact) {
|
|
2425
3138
|
return;
|
|
2426
3139
|
}
|
|
@@ -2439,7 +3152,7 @@ function ChatView({
|
|
|
2439
3152
|
});
|
|
2440
3153
|
}
|
|
2441
3154
|
}, [messages, onArtifact]);
|
|
2442
|
-
const abortRef = (0,
|
|
3155
|
+
const abortRef = (0, import_react14.useRef)(null);
|
|
2443
3156
|
const { containerRef, isFollowing, scrollToBottom } = useChatAutoScroll({
|
|
2444
3157
|
messageCount: messages.length,
|
|
2445
3158
|
lastContentLength: lastContentLength(messages),
|
|
@@ -2450,7 +3163,7 @@ function ChatView({
|
|
|
2450
3163
|
model,
|
|
2451
3164
|
onModelChange
|
|
2452
3165
|
});
|
|
2453
|
-
const [contextChips, setContextChips] = (0,
|
|
3166
|
+
const [contextChips, setContextChips] = (0, import_react14.useState)([]);
|
|
2454
3167
|
const handleContextChipsChange = (chips) => {
|
|
2455
3168
|
setContextChips(chips);
|
|
2456
3169
|
onContextsChange?.(chips);
|
|
@@ -2482,6 +3195,16 @@ function ChatView({
|
|
|
2482
3195
|
abortRef.current?.abort();
|
|
2483
3196
|
abortRef.current = null;
|
|
2484
3197
|
};
|
|
3198
|
+
const handleSendRef = (0, import_react14.useRef)(handleSend);
|
|
3199
|
+
handleSendRef.current = handleSend;
|
|
3200
|
+
const onOpenArtifactRef = (0, import_react14.useRef)(onOpenArtifact);
|
|
3201
|
+
onOpenArtifactRef.current = onOpenArtifact;
|
|
3202
|
+
(0, import_react14.useEffect)(() => {
|
|
3203
|
+
setChatChromeHandlers({
|
|
3204
|
+
sendSuggestion: (text) => handleSendRef.current(text),
|
|
3205
|
+
openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact)
|
|
3206
|
+
});
|
|
3207
|
+
}, []);
|
|
2485
3208
|
const handleRegenerate = () => {
|
|
2486
3209
|
if (!transport) {
|
|
2487
3210
|
return;
|
|
@@ -2499,7 +3222,7 @@ function ChatView({
|
|
|
2499
3222
|
const lastMessage = messages[messages.length - 1];
|
|
2500
3223
|
const regenerableMessageId = lastMessage?.role === "assistant" && lastMessage.status === "completed" ? lastMessage.id : void 0;
|
|
2501
3224
|
const isEmpty = messages.length === 0;
|
|
2502
|
-
const composerNode = /* @__PURE__ */ (0,
|
|
3225
|
+
const composerNode = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2503
3226
|
Composer,
|
|
2504
3227
|
{
|
|
2505
3228
|
onSend: handleSend,
|
|
@@ -2511,6 +3234,8 @@ function ChatView({
|
|
|
2511
3234
|
onAttachmentClick,
|
|
2512
3235
|
toolbarStart,
|
|
2513
3236
|
toolbarEnd,
|
|
3237
|
+
composerFooter,
|
|
3238
|
+
hideToolbar,
|
|
2514
3239
|
onMentionTrigger,
|
|
2515
3240
|
onPlusMenu,
|
|
2516
3241
|
models: modelPlacement === "header" ? void 0 : models,
|
|
@@ -2522,14 +3247,18 @@ function ChatView({
|
|
|
2522
3247
|
callService
|
|
2523
3248
|
}
|
|
2524
3249
|
);
|
|
2525
|
-
|
|
3250
|
+
const composerDock = /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-view__composer-dock", children: [
|
|
3251
|
+
composerNode,
|
|
3252
|
+
composerBottom !== void 0 && composerBottom !== null ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "pactor-chat-view__composer-bottom", children: composerBottom }) : null
|
|
3253
|
+
] });
|
|
3254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2526
3255
|
"div",
|
|
2527
3256
|
{
|
|
2528
3257
|
className: `pactor-chat-view${isEmpty ? " pactor-chat-view--empty" : ""}${className ? ` ${className}` : ""}`,
|
|
2529
3258
|
children: [
|
|
2530
|
-
/* @__PURE__ */ (0,
|
|
2531
|
-
isEmpty ? /* @__PURE__ */ (0,
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
3259
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-messages", ref: containerRef, children: [
|
|
3260
|
+
isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-view__empty-stack", children: [
|
|
3261
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2533
3262
|
EmptyState,
|
|
2534
3263
|
{
|
|
2535
3264
|
greeting,
|
|
@@ -2538,8 +3267,8 @@ function ChatView({
|
|
|
2538
3267
|
onSuggestionClick: handleSend
|
|
2539
3268
|
}
|
|
2540
3269
|
),
|
|
2541
|
-
|
|
2542
|
-
] }) : messages.map((message) => /* @__PURE__ */ (0,
|
|
3270
|
+
composerDock
|
|
3271
|
+
] }) : messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2543
3272
|
MessageBubble,
|
|
2544
3273
|
{
|
|
2545
3274
|
message,
|
|
@@ -2556,28 +3285,28 @@ function ChatView({
|
|
|
2556
3285
|
},
|
|
2557
3286
|
message.id
|
|
2558
3287
|
)),
|
|
2559
|
-
!isFollowing && /* @__PURE__ */ (0,
|
|
3288
|
+
!isFollowing && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2560
3289
|
"button",
|
|
2561
3290
|
{
|
|
2562
3291
|
type: "button",
|
|
2563
3292
|
className: "pactor-chat-scroll-bottom",
|
|
2564
3293
|
onClick: scrollToBottom,
|
|
2565
3294
|
children: [
|
|
2566
|
-
/* @__PURE__ */ (0,
|
|
3295
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_components10.Icon, { name: "arrow-down", size: 13 }),
|
|
2567
3296
|
"\u56DE\u5230\u5E95\u90E8"
|
|
2568
3297
|
]
|
|
2569
3298
|
}
|
|
2570
3299
|
)
|
|
2571
3300
|
] }),
|
|
2572
|
-
!isEmpty &&
|
|
3301
|
+
!isEmpty && composerDock
|
|
2573
3302
|
]
|
|
2574
3303
|
}
|
|
2575
3304
|
);
|
|
2576
3305
|
}
|
|
2577
3306
|
|
|
2578
3307
|
// src/view/WorkspaceHeader.tsx
|
|
2579
|
-
var
|
|
2580
|
-
var
|
|
3308
|
+
var import_components11 = require("@pactor-app/ui/components");
|
|
3309
|
+
var import_react15 = require("react");
|
|
2581
3310
|
|
|
2582
3311
|
// src/export-markdown.ts
|
|
2583
3312
|
var ROLE_LABELS = {
|
|
@@ -2609,8 +3338,52 @@ function downloadMessagesAsMarkdown(title, messages) {
|
|
|
2609
3338
|
URL.revokeObjectURL(url);
|
|
2610
3339
|
}
|
|
2611
3340
|
|
|
3341
|
+
// src/view/chrome/header-actions.tsx
|
|
3342
|
+
function buildHeaderActionsFragment(props) {
|
|
3343
|
+
const meta = {
|
|
3344
|
+
export: { label: "\u5BFC\u51FA Markdown", icon: "download" },
|
|
3345
|
+
theme: {
|
|
3346
|
+
label: props.theme === "dark" ? "\u5207\u6362\u4E3A\u6D45\u8272" : "\u5207\u6362\u4E3A\u6DF1\u8272",
|
|
3347
|
+
icon: props.theme === "dark" ? "sun" : "moon"
|
|
3348
|
+
},
|
|
3349
|
+
clear: { label: "\u6E05\u7A7A\u4F1A\u8BDD", icon: "trash2" }
|
|
3350
|
+
};
|
|
3351
|
+
return {
|
|
3352
|
+
requires: ["Flex", "Tooltip", "Button", "Icon"],
|
|
3353
|
+
node: {
|
|
3354
|
+
type: "Flex",
|
|
3355
|
+
props: { gap: "small", align: "center" },
|
|
3356
|
+
children: props.actions.map((action) => ({
|
|
3357
|
+
type: "Tooltip",
|
|
3358
|
+
props: { content: meta[action].label },
|
|
3359
|
+
children: [
|
|
3360
|
+
{
|
|
3361
|
+
type: "Button",
|
|
3362
|
+
props: {
|
|
3363
|
+
variant: "text",
|
|
3364
|
+
size: "small",
|
|
3365
|
+
className: "pactor-chat-icon-button"
|
|
3366
|
+
},
|
|
3367
|
+
events: {
|
|
3368
|
+
onClick: [
|
|
3369
|
+
{ action: "chat.headerAction", params: { action } }
|
|
3370
|
+
]
|
|
3371
|
+
},
|
|
3372
|
+
children: [
|
|
3373
|
+
{
|
|
3374
|
+
type: "Icon",
|
|
3375
|
+
props: { name: meta[action].icon, size: 15 }
|
|
3376
|
+
}
|
|
3377
|
+
]
|
|
3378
|
+
}
|
|
3379
|
+
]
|
|
3380
|
+
}))
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
}
|
|
3384
|
+
|
|
2612
3385
|
// src/view/WorkspaceHeader.tsx
|
|
2613
|
-
var
|
|
3386
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2614
3387
|
function readCurrentTheme() {
|
|
2615
3388
|
if (typeof document === "undefined") {
|
|
2616
3389
|
return "light";
|
|
@@ -2630,10 +3403,10 @@ function WorkspaceHeader({
|
|
|
2630
3403
|
onTitleChange
|
|
2631
3404
|
}) {
|
|
2632
3405
|
const hasActions = headerActions !== void 0 && headerActions.length > 0;
|
|
2633
|
-
const [overrideTitle, setOverrideTitle] = (0,
|
|
2634
|
-
const [editing, setEditing] = (0,
|
|
2635
|
-
const [draft, setDraft] = (0,
|
|
2636
|
-
const prevTitleRef = (0,
|
|
3406
|
+
const [overrideTitle, setOverrideTitle] = (0, import_react15.useState)(null);
|
|
3407
|
+
const [editing, setEditing] = (0, import_react15.useState)(false);
|
|
3408
|
+
const [draft, setDraft] = (0, import_react15.useState)("");
|
|
3409
|
+
const prevTitleRef = (0, import_react15.useRef)(title);
|
|
2637
3410
|
if (prevTitleRef.current !== title) {
|
|
2638
3411
|
prevTitleRef.current = title;
|
|
2639
3412
|
if (overrideTitle !== null) {
|
|
@@ -2641,7 +3414,7 @@ function WorkspaceHeader({
|
|
|
2641
3414
|
}
|
|
2642
3415
|
}
|
|
2643
3416
|
const displayTitle = overrideTitle ?? title;
|
|
2644
|
-
const [theme, setTheme] = (0,
|
|
3417
|
+
const [theme, setTheme] = (0, import_react15.useState)(readCurrentTheme);
|
|
2645
3418
|
const commitTitle = () => {
|
|
2646
3419
|
setEditing(false);
|
|
2647
3420
|
const next = draft.trim();
|
|
@@ -2668,8 +3441,24 @@ function WorkspaceHeader({
|
|
|
2668
3441
|
store.clear();
|
|
2669
3442
|
onClear?.();
|
|
2670
3443
|
};
|
|
3444
|
+
const handlersRef = (0, import_react15.useRef)({ handleExport, handleTheme, handleClear });
|
|
3445
|
+
handlersRef.current = { handleExport, handleTheme, handleClear };
|
|
3446
|
+
(0, import_react15.useEffect)(() => {
|
|
3447
|
+
setChatChromeHandlers({
|
|
3448
|
+
headerAction: (name) => {
|
|
3449
|
+
const handlers2 = handlersRef.current;
|
|
3450
|
+
if (name === "export") {
|
|
3451
|
+
handlers2.handleExport();
|
|
3452
|
+
} else if (name === "theme") {
|
|
3453
|
+
handlers2.handleTheme();
|
|
3454
|
+
} else if (name === "clear") {
|
|
3455
|
+
handlers2.handleClear();
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
});
|
|
3459
|
+
}, []);
|
|
2671
3460
|
const actionButtons = {
|
|
2672
|
-
export: /* @__PURE__ */ (0,
|
|
3461
|
+
export: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2673
3462
|
"button",
|
|
2674
3463
|
{
|
|
2675
3464
|
type: "button",
|
|
@@ -2677,11 +3466,11 @@ function WorkspaceHeader({
|
|
|
2677
3466
|
title: "\u5BFC\u51FA Markdown",
|
|
2678
3467
|
"aria-label": "\u5BFC\u51FA Markdown",
|
|
2679
3468
|
onClick: handleExport,
|
|
2680
|
-
children: /* @__PURE__ */ (0,
|
|
3469
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "download", size: 15 })
|
|
2681
3470
|
},
|
|
2682
3471
|
"export"
|
|
2683
3472
|
),
|
|
2684
|
-
theme: /* @__PURE__ */ (0,
|
|
3473
|
+
theme: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2685
3474
|
"button",
|
|
2686
3475
|
{
|
|
2687
3476
|
type: "button",
|
|
@@ -2689,11 +3478,11 @@ function WorkspaceHeader({
|
|
|
2689
3478
|
title: theme === "dark" ? "\u5207\u6362\u4E3A\u6D45\u8272" : "\u5207\u6362\u4E3A\u6DF1\u8272",
|
|
2690
3479
|
"aria-label": "\u5207\u6362\u660E\u6697\u4E3B\u9898",
|
|
2691
3480
|
onClick: handleTheme,
|
|
2692
|
-
children: theme === "dark" ? /* @__PURE__ */ (0,
|
|
3481
|
+
children: theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "sun", size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "moon", size: 15 })
|
|
2693
3482
|
},
|
|
2694
3483
|
"theme"
|
|
2695
3484
|
),
|
|
2696
|
-
clear: /* @__PURE__ */ (0,
|
|
3485
|
+
clear: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2697
3486
|
"button",
|
|
2698
3487
|
{
|
|
2699
3488
|
type: "button",
|
|
@@ -2701,12 +3490,12 @@ function WorkspaceHeader({
|
|
|
2701
3490
|
title: "\u6E05\u7A7A\u4F1A\u8BDD",
|
|
2702
3491
|
"aria-label": "\u6E05\u7A7A\u4F1A\u8BDD",
|
|
2703
3492
|
onClick: handleClear,
|
|
2704
|
-
children: /* @__PURE__ */ (0,
|
|
3493
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "trash", size: 15 })
|
|
2705
3494
|
},
|
|
2706
3495
|
"clear"
|
|
2707
3496
|
)
|
|
2708
3497
|
};
|
|
2709
|
-
const titleNode = editableTitle ? editing ? /* @__PURE__ */ (0,
|
|
3498
|
+
const titleNode = editableTitle ? editing ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2710
3499
|
"input",
|
|
2711
3500
|
{
|
|
2712
3501
|
className: "pactor-chat-workspace__title-input",
|
|
@@ -2723,7 +3512,7 @@ function WorkspaceHeader({
|
|
|
2723
3512
|
}
|
|
2724
3513
|
}
|
|
2725
3514
|
}
|
|
2726
|
-
) : /* @__PURE__ */ (0,
|
|
3515
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2727
3516
|
"button",
|
|
2728
3517
|
{
|
|
2729
3518
|
type: "button",
|
|
@@ -2735,29 +3524,38 @@ function WorkspaceHeader({
|
|
|
2735
3524
|
},
|
|
2736
3525
|
children: displayTitle
|
|
2737
3526
|
}
|
|
2738
|
-
) : /* @__PURE__ */ (0,
|
|
2739
|
-
return /* @__PURE__ */ (0,
|
|
3527
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__title", children: title });
|
|
3528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "pactor-chat-workspace__header", children: [
|
|
2740
3529
|
headerStart !== void 0 ? (
|
|
2741
3530
|
// header 位模型 chip(决策 D2):与 title 组成左端组,chip 在前
|
|
2742
|
-
/* @__PURE__ */ (0,
|
|
3531
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-workspace__header-left", children: [
|
|
2743
3532
|
headerStart,
|
|
2744
3533
|
titleNode
|
|
2745
3534
|
] })
|
|
2746
3535
|
) : titleNode,
|
|
2747
|
-
hasActions ? /* @__PURE__ */ (0,
|
|
2748
|
-
/* @__PURE__ */ (0,
|
|
2749
|
-
|
|
2750
|
-
|
|
3536
|
+
hasActions ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-workspace__header-right", children: [
|
|
3537
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-actions", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3538
|
+
ChromeSlot,
|
|
3539
|
+
{
|
|
3540
|
+
fragment: buildHeaderActionsFragment({
|
|
3541
|
+
actions: headerActions,
|
|
3542
|
+
theme
|
|
3543
|
+
}),
|
|
3544
|
+
fallback: headerActions.map((action) => actionButtons[action])
|
|
3545
|
+
}
|
|
3546
|
+
) }),
|
|
3547
|
+
headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
|
|
3548
|
+
] }) : headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
|
|
2751
3549
|
] });
|
|
2752
3550
|
}
|
|
2753
3551
|
|
|
2754
3552
|
// src/chat-composition.tsx
|
|
2755
|
-
var
|
|
3553
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2756
3554
|
function DslNodeSlotInner({ node }) {
|
|
2757
|
-
const { renderChildren } = (0,
|
|
3555
|
+
const { renderChildren } = (0, import_runtime5.useRenderer)();
|
|
2758
3556
|
return renderChildren([node]);
|
|
2759
3557
|
}
|
|
2760
|
-
var DslSlotGuard = class extends
|
|
3558
|
+
var DslSlotGuard = class extends import_react16.Component {
|
|
2761
3559
|
constructor() {
|
|
2762
3560
|
super(...arguments);
|
|
2763
3561
|
this.state = { failed: false };
|
|
@@ -2775,17 +3573,17 @@ var DslSlotGuard = class extends import_react15.Component {
|
|
|
2775
3573
|
}
|
|
2776
3574
|
};
|
|
2777
3575
|
function DslNodeSlot({ node }) {
|
|
2778
|
-
return /* @__PURE__ */ (0,
|
|
3576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslSlotGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslNodeSlotInner, { node }) });
|
|
2779
3577
|
}
|
|
2780
3578
|
function isDslNodeValue(value) {
|
|
2781
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && !(0,
|
|
3579
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(0, import_react16.isValidElement)(value) && typeof value.type === "string";
|
|
2782
3580
|
}
|
|
2783
3581
|
function resolveSlot(slot) {
|
|
2784
3582
|
if (slot === void 0 || slot === null) {
|
|
2785
3583
|
return void 0;
|
|
2786
3584
|
}
|
|
2787
3585
|
if (isDslNodeValue(slot)) {
|
|
2788
|
-
return /* @__PURE__ */ (0,
|
|
3586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslNodeSlot, { node: slot });
|
|
2789
3587
|
}
|
|
2790
3588
|
return slot;
|
|
2791
3589
|
}
|
|
@@ -2815,7 +3613,11 @@ function ChatComposition({
|
|
|
2815
3613
|
messageActions,
|
|
2816
3614
|
onMessageAction,
|
|
2817
3615
|
sidebar,
|
|
3616
|
+
toolbarStart,
|
|
2818
3617
|
toolbarEnd,
|
|
3618
|
+
composerFooter,
|
|
3619
|
+
composerBottom,
|
|
3620
|
+
hideToolbar,
|
|
2819
3621
|
className,
|
|
2820
3622
|
onSend,
|
|
2821
3623
|
artifact,
|
|
@@ -2825,18 +3627,18 @@ function ChatComposition({
|
|
|
2825
3627
|
onArtifact,
|
|
2826
3628
|
onOpenArtifact
|
|
2827
3629
|
}) {
|
|
2828
|
-
const storeRef = (0,
|
|
3630
|
+
const storeRef = (0, import_react16.useRef)(null);
|
|
2829
3631
|
if (storeRef.current === null) {
|
|
2830
3632
|
storeRef.current = services.store ?? services.storeFactory?.() ?? new ConversationStore();
|
|
2831
3633
|
}
|
|
2832
3634
|
const store = storeRef.current;
|
|
2833
|
-
const artifactStoreRef = (0,
|
|
3635
|
+
const artifactStoreRef = (0, import_react16.useRef)(null);
|
|
2834
3636
|
if (artifactStoreRef.current === null) {
|
|
2835
3637
|
artifactStoreRef.current = services.artifactStore ?? new ArtifactStore();
|
|
2836
3638
|
}
|
|
2837
3639
|
const artifactStore = artifactStoreRef.current;
|
|
2838
3640
|
const panelControlled = panelOpen !== void 0 || artifact !== void 0;
|
|
2839
|
-
const storeArtifact = (0,
|
|
3641
|
+
const storeArtifact = (0, import_react16.useSyncExternalStore)(
|
|
2840
3642
|
(listener) => artifactStore.subscribe(listener),
|
|
2841
3643
|
() => artifactStore.get()
|
|
2842
3644
|
);
|
|
@@ -2854,7 +3656,7 @@ function ChatComposition({
|
|
|
2854
3656
|
artifactStore.open(next);
|
|
2855
3657
|
}
|
|
2856
3658
|
};
|
|
2857
|
-
const [attachments, setAttachments] = (0,
|
|
3659
|
+
const [attachments, setAttachments] = (0, import_react16.useState)([]);
|
|
2858
3660
|
const handleAttachFiles = services.onAttachFiles ? (files) => {
|
|
2859
3661
|
void Promise.resolve(services.onAttachFiles(files)).then(
|
|
2860
3662
|
(created) => {
|
|
@@ -2874,24 +3676,38 @@ function ChatComposition({
|
|
|
2874
3676
|
model,
|
|
2875
3677
|
onModelChange
|
|
2876
3678
|
});
|
|
2877
|
-
const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ (0,
|
|
2878
|
-
|
|
3679
|
+
const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3680
|
+
ModelSelect,
|
|
2879
3681
|
{
|
|
2880
3682
|
models,
|
|
2881
3683
|
model: currentModel,
|
|
2882
3684
|
onModelChange: handleModelChange
|
|
2883
3685
|
}
|
|
2884
3686
|
) : void 0;
|
|
2885
|
-
const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ (0,
|
|
3687
|
+
const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
2886
3688
|
services.toolbarEnd,
|
|
2887
3689
|
toolbarEnd
|
|
2888
3690
|
] }) : void 0;
|
|
2889
|
-
const
|
|
3691
|
+
const mergedToolbarStart = services.toolbarStart !== void 0 || toolbarStart !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3692
|
+
services.toolbarStart,
|
|
3693
|
+
toolbarStart
|
|
3694
|
+
] }) : void 0;
|
|
3695
|
+
const mergedComposerFooter = services.composerFooter !== void 0 || composerFooter !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3696
|
+
services.composerFooter,
|
|
3697
|
+
composerFooter
|
|
3698
|
+
] }) : void 0;
|
|
3699
|
+
const mergedComposerBottom = services.composerBottom !== void 0 || composerBottom !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3700
|
+
services.composerBottom,
|
|
3701
|
+
composerBottom
|
|
3702
|
+
] }) : void 0;
|
|
3703
|
+
const hasHeaderContent = header !== void 0 && header !== null ? true : title !== void 0 || headerExtra !== void 0 && headerExtra !== null || headerActions !== void 0 && headerActions.length > 0 || headerModelChip !== void 0;
|
|
3704
|
+
const renderHeader = showHeader !== false && hasHeaderContent;
|
|
3705
|
+
const workspace = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2890
3706
|
"div",
|
|
2891
3707
|
{
|
|
2892
3708
|
className: `pactor-chat-workspace${className ? ` ${className}` : ""}`,
|
|
2893
3709
|
children: [
|
|
2894
|
-
|
|
3710
|
+
renderHeader ? header ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2895
3711
|
WorkspaceHeader,
|
|
2896
3712
|
{
|
|
2897
3713
|
title,
|
|
@@ -2906,7 +3722,7 @@ function ChatComposition({
|
|
|
2906
3722
|
onTitleChange
|
|
2907
3723
|
}
|
|
2908
3724
|
) : null,
|
|
2909
|
-
/* @__PURE__ */ (0,
|
|
3725
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2910
3726
|
ChatView,
|
|
2911
3727
|
{
|
|
2912
3728
|
store,
|
|
@@ -2926,8 +3742,11 @@ function ChatComposition({
|
|
|
2926
3742
|
onAttachmentsChange: setAttachments,
|
|
2927
3743
|
onAttachFiles: handleAttachFiles,
|
|
2928
3744
|
onAttachmentClick: services.onAttachmentClick,
|
|
2929
|
-
toolbarStart:
|
|
3745
|
+
toolbarStart: mergedToolbarStart,
|
|
2930
3746
|
toolbarEnd: mergedToolbarEnd,
|
|
3747
|
+
composerFooter: mergedComposerFooter,
|
|
3748
|
+
composerBottom: mergedComposerBottom,
|
|
3749
|
+
hideToolbar,
|
|
2931
3750
|
onMentionTrigger: services.onMentionTrigger,
|
|
2932
3751
|
onPlusMenu: services.onPlusMenu,
|
|
2933
3752
|
onArtifact,
|
|
@@ -2946,15 +3765,15 @@ function ChatComposition({
|
|
|
2946
3765
|
]
|
|
2947
3766
|
}
|
|
2948
3767
|
);
|
|
2949
|
-
const main = sidebar ? /* @__PURE__ */ (0,
|
|
3768
|
+
const main = sidebar ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AppShell, { sidebar, children: workspace }) : workspace;
|
|
2950
3769
|
const panelFeatureUsed = artifact !== void 0 || panelOpen !== void 0 || inspector !== void 0 || onPanelClose !== void 0 || onArtifact !== void 0 || onOpenArtifact !== void 0 || services.artifactStore !== void 0;
|
|
2951
3770
|
if (!panelFeatureUsed && !effectivePanelOpen) {
|
|
2952
3771
|
return main;
|
|
2953
3772
|
}
|
|
2954
|
-
return /* @__PURE__ */ (0,
|
|
3773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "pactor-chat-inspector-host", children: [
|
|
2955
3774
|
main,
|
|
2956
|
-
effectivePanelOpen ? /* @__PURE__ */ (0,
|
|
2957
|
-
/* @__PURE__ */ (0,
|
|
3775
|
+
effectivePanelOpen ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3776
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2958
3777
|
"div",
|
|
2959
3778
|
{
|
|
2960
3779
|
className: "pactor-chat-inspector__scrim",
|
|
@@ -2962,7 +3781,7 @@ function ChatComposition({
|
|
|
2962
3781
|
onClick: handlePanelClose
|
|
2963
3782
|
}
|
|
2964
3783
|
),
|
|
2965
|
-
/* @__PURE__ */ (0,
|
|
3784
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2966
3785
|
ArtifactPanel,
|
|
2967
3786
|
{
|
|
2968
3787
|
artifact: effectiveArtifact,
|
|
@@ -2977,21 +3796,21 @@ function ChatComposition({
|
|
|
2977
3796
|
}
|
|
2978
3797
|
|
|
2979
3798
|
// src/chat-services.tsx
|
|
2980
|
-
var
|
|
2981
|
-
var
|
|
2982
|
-
var ChatServicesContext = (0,
|
|
3799
|
+
var import_react17 = require("react");
|
|
3800
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3801
|
+
var ChatServicesContext = (0, import_react17.createContext)(null);
|
|
2983
3802
|
function ChatServicesProvider({
|
|
2984
3803
|
value,
|
|
2985
3804
|
children
|
|
2986
3805
|
}) {
|
|
2987
|
-
return /* @__PURE__ */ (0,
|
|
3806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChatServicesContext.Provider, { value, children });
|
|
2988
3807
|
}
|
|
2989
3808
|
function useChatServices() {
|
|
2990
|
-
return (0,
|
|
3809
|
+
return (0, import_react17.useContext)(ChatServicesContext);
|
|
2991
3810
|
}
|
|
2992
3811
|
|
|
2993
3812
|
// src/chat-workspace.tsx
|
|
2994
|
-
var
|
|
3813
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2995
3814
|
function createChatWorkspace(services) {
|
|
2996
3815
|
function ChatWorkspace({
|
|
2997
3816
|
title,
|
|
@@ -3001,7 +3820,11 @@ function createChatWorkspace(services) {
|
|
|
3001
3820
|
conversationId,
|
|
3002
3821
|
params,
|
|
3003
3822
|
sidebar,
|
|
3823
|
+
toolbarStart,
|
|
3004
3824
|
toolbarEnd,
|
|
3825
|
+
composerFooter,
|
|
3826
|
+
composerBottom,
|
|
3827
|
+
hideToolbar,
|
|
3005
3828
|
artifact,
|
|
3006
3829
|
panelOpen,
|
|
3007
3830
|
onPanelClose,
|
|
@@ -3024,7 +3847,7 @@ function createChatWorkspace(services) {
|
|
|
3024
3847
|
onMessageAction,
|
|
3025
3848
|
className
|
|
3026
3849
|
}) {
|
|
3027
|
-
return /* @__PURE__ */ (0,
|
|
3850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatServicesProvider, { value: services, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
3028
3851
|
ChatComposition,
|
|
3029
3852
|
{
|
|
3030
3853
|
services,
|
|
@@ -3035,15 +3858,17 @@ function createChatWorkspace(services) {
|
|
|
3035
3858
|
conversationId,
|
|
3036
3859
|
params,
|
|
3037
3860
|
className,
|
|
3038
|
-
showHeader: title !== void 0 || services.headerExtra !== void 0 || // header 位模型 chip(决策 D2):仅配置 models 也渲染极简头部
|
|
3039
|
-
modelPlacement === "header" && models !== void 0 && models.length > 0,
|
|
3040
3861
|
headerExtra: services.headerExtra,
|
|
3041
|
-
sidebar: sidebar ? /* @__PURE__ */ (0,
|
|
3042
|
-
|
|
3862
|
+
sidebar: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: sidebar }) : void 0,
|
|
3863
|
+
toolbarStart: toolbarStart ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: toolbarStart }) : void 0,
|
|
3864
|
+
toolbarEnd: toolbarEnd ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: toolbarEnd }) : void 0,
|
|
3865
|
+
composerFooter: composerFooter ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: composerFooter }) : void 0,
|
|
3866
|
+
composerBottom: composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: composerBottom }) : void 0,
|
|
3867
|
+
hideToolbar,
|
|
3043
3868
|
artifact,
|
|
3044
3869
|
panelOpen,
|
|
3045
3870
|
onPanelClose,
|
|
3046
|
-
inspector: inspector ? /* @__PURE__ */ (0,
|
|
3871
|
+
inspector: inspector ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: inspector }) : void 0,
|
|
3047
3872
|
onArtifact,
|
|
3048
3873
|
onOpenArtifact,
|
|
3049
3874
|
headerActions,
|
|
@@ -3067,11 +3892,37 @@ function createChatWorkspace(services) {
|
|
|
3067
3892
|
}
|
|
3068
3893
|
|
|
3069
3894
|
// src/view/Chat.tsx
|
|
3070
|
-
var
|
|
3071
|
-
var
|
|
3895
|
+
var import_components12 = require("@pactor-app/ui/components");
|
|
3896
|
+
var import_react18 = require("react");
|
|
3897
|
+
|
|
3898
|
+
// src/view/chrome/menu.tsx
|
|
3899
|
+
function buildSidebarMenuFragment(props) {
|
|
3900
|
+
return {
|
|
3901
|
+
requires: ["Menu"],
|
|
3902
|
+
node: {
|
|
3903
|
+
type: "Menu",
|
|
3904
|
+
props: {
|
|
3905
|
+
mode: "inline",
|
|
3906
|
+
selectedKey: props.activeMenuKey,
|
|
3907
|
+
items: props.menu.map((item) => ({
|
|
3908
|
+
key: item.key,
|
|
3909
|
+
label: item.label,
|
|
3910
|
+
...item.icon !== void 0 ? { icon: item.icon } : {},
|
|
3911
|
+
...item.badge !== void 0 ? { badge: item.badge } : {},
|
|
3912
|
+
...item.dot === true ? { dot: true } : {},
|
|
3913
|
+
...item.group !== void 0 ? { group: item.group } : {},
|
|
3914
|
+
...item.disabled === true ? { disabled: true } : {}
|
|
3915
|
+
}))
|
|
3916
|
+
},
|
|
3917
|
+
events: {
|
|
3918
|
+
onSelect: [{ action: "chat.menuSelect", params: { key: "${event}" } }]
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
};
|
|
3922
|
+
}
|
|
3072
3923
|
|
|
3073
3924
|
// src/view/ChatShell.tsx
|
|
3074
|
-
var
|
|
3925
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
3075
3926
|
function ChatShell({
|
|
3076
3927
|
menu,
|
|
3077
3928
|
activeMenuKey,
|
|
@@ -3083,7 +3934,7 @@ function ChatShell({
|
|
|
3083
3934
|
className,
|
|
3084
3935
|
onMenuSelect
|
|
3085
3936
|
}) {
|
|
3086
|
-
const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0,
|
|
3937
|
+
const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3087
3938
|
ChatSidebarMenu,
|
|
3088
3939
|
{
|
|
3089
3940
|
menu,
|
|
@@ -3091,7 +3942,7 @@ function ChatShell({
|
|
|
3091
3942
|
onMenuSelect
|
|
3092
3943
|
}
|
|
3093
3944
|
) : null);
|
|
3094
|
-
return /* @__PURE__ */ (0,
|
|
3945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3095
3946
|
AppShell,
|
|
3096
3947
|
{
|
|
3097
3948
|
sidebar: sidebarContent,
|
|
@@ -3108,7 +3959,7 @@ function ChatShellDslAdapter({
|
|
|
3108
3959
|
onMenuSelect,
|
|
3109
3960
|
...rest
|
|
3110
3961
|
}) {
|
|
3111
|
-
return /* @__PURE__ */ (0,
|
|
3962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3112
3963
|
ChatShell,
|
|
3113
3964
|
{
|
|
3114
3965
|
...rest,
|
|
@@ -3123,39 +3974,45 @@ function registerChatShellComponent(registry) {
|
|
|
3123
3974
|
}
|
|
3124
3975
|
|
|
3125
3976
|
// src/view/Chat.tsx
|
|
3126
|
-
var
|
|
3127
|
-
var MENU_ICONS = {
|
|
3128
|
-
plus: import_lucide_react10.Plus,
|
|
3129
|
-
chat: import_lucide_react10.MessageSquare,
|
|
3130
|
-
history: import_lucide_react10.History,
|
|
3131
|
-
settings: import_lucide_react10.Settings,
|
|
3132
|
-
star: import_lucide_react10.Star,
|
|
3133
|
-
search: import_lucide_react10.Search,
|
|
3134
|
-
user: import_lucide_react10.User,
|
|
3135
|
-
folder: import_lucide_react10.Folder
|
|
3136
|
-
};
|
|
3977
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3137
3978
|
function ChatSidebarMenu({
|
|
3138
3979
|
menu,
|
|
3139
3980
|
activeMenuKey,
|
|
3140
3981
|
onMenuSelect
|
|
3141
3982
|
}) {
|
|
3142
3983
|
const drawer = useSidebarDrawer();
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3984
|
+
const menuRef = (0, import_react18.useRef)(menu);
|
|
3985
|
+
menuRef.current = menu;
|
|
3986
|
+
const selectRef = (0, import_react18.useRef)(onMenuSelect);
|
|
3987
|
+
selectRef.current = onMenuSelect;
|
|
3988
|
+
const drawerRef = (0, import_react18.useRef)(drawer);
|
|
3989
|
+
drawerRef.current = drawer;
|
|
3990
|
+
(0, import_react18.useEffect)(() => {
|
|
3991
|
+
setChatChromeHandlers({
|
|
3992
|
+
menuSelect: (key) => {
|
|
3993
|
+
const item = menuRef.current.find((entry) => entry.key === key);
|
|
3994
|
+
if (item === void 0 || item.disabled === true) {
|
|
3995
|
+
return;
|
|
3996
|
+
}
|
|
3997
|
+
selectRef.current?.(key, item);
|
|
3998
|
+
drawerRef.current?.close();
|
|
3999
|
+
}
|
|
4000
|
+
});
|
|
4001
|
+
}, []);
|
|
4002
|
+
const fallback = (() => {
|
|
4003
|
+
let lastGroup;
|
|
4004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("nav", { className: "pactor-chat-menu", "aria-label": "\u4F1A\u8BDD\u5BFC\u822A", children: menu.map((item) => {
|
|
4005
|
+
const groupLabel = item.group !== void 0 && item.group !== lastGroup ? item.group : void 0;
|
|
4006
|
+
lastGroup = item.group;
|
|
4007
|
+
const active = item.key === activeMenuKey;
|
|
4008
|
+
const collapsed = drawer?.collapsed === true;
|
|
4009
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3152
4010
|
"button",
|
|
3153
4011
|
{
|
|
3154
4012
|
type: "button",
|
|
3155
4013
|
className: `pactor-chat-menu__item${active ? " pactor-chat-menu__item--active" : ""}`,
|
|
3156
4014
|
disabled: item.disabled === true,
|
|
3157
4015
|
"aria-current": active ? "true" : void 0,
|
|
3158
|
-
title: drawer?.collapsed ? item.label : void 0,
|
|
3159
4016
|
onClick: () => {
|
|
3160
4017
|
if (item.disabled) {
|
|
3161
4018
|
return;
|
|
@@ -3164,21 +4021,26 @@ function ChatSidebarMenu({
|
|
|
3164
4021
|
drawer?.close();
|
|
3165
4022
|
},
|
|
3166
4023
|
children: [
|
|
3167
|
-
item.icon !== void 0 ?
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
"aria-hidden": true
|
|
3172
|
-
}
|
|
3173
|
-
) : null,
|
|
3174
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "pactor-chat-menu__label", children: item.label }),
|
|
3175
|
-
item.dot === true ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
|
|
3176
|
-
item.badge !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
|
|
4024
|
+
item.icon !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__icon", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components12.Icon, { name: item.icon, size: 15, strokeWidth: 1.7 }) }) : null,
|
|
4025
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__label", children: item.label }),
|
|
4026
|
+
item.dot === true ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
|
|
4027
|
+
item.badge !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
|
|
3177
4028
|
]
|
|
3178
4029
|
}
|
|
3179
|
-
)
|
|
3180
|
-
|
|
3181
|
-
|
|
4030
|
+
);
|
|
4031
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react18.Fragment, { children: [
|
|
4032
|
+
groupLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
|
|
4033
|
+
collapsed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components12.RailTooltip, { label: item.label, children: button }) : button
|
|
4034
|
+
] }, item.key);
|
|
4035
|
+
}) });
|
|
4036
|
+
})();
|
|
4037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4038
|
+
ChromeSlot,
|
|
4039
|
+
{
|
|
4040
|
+
fragment: buildSidebarMenuFragment({ menu, activeMenuKey }),
|
|
4041
|
+
fallback
|
|
4042
|
+
}
|
|
4043
|
+
);
|
|
3182
4044
|
}
|
|
3183
4045
|
function Chat({
|
|
3184
4046
|
title,
|
|
@@ -3191,6 +4053,11 @@ function Chat({
|
|
|
3191
4053
|
menu,
|
|
3192
4054
|
activeMenuKey,
|
|
3193
4055
|
sidebar,
|
|
4056
|
+
toolbarStart,
|
|
4057
|
+
toolbarEnd,
|
|
4058
|
+
composerFooter,
|
|
4059
|
+
composerBottom,
|
|
4060
|
+
hideToolbar,
|
|
3194
4061
|
headerExtra,
|
|
3195
4062
|
header,
|
|
3196
4063
|
headerActions,
|
|
@@ -3218,7 +4085,7 @@ function Chat({
|
|
|
3218
4085
|
onMenuSelect
|
|
3219
4086
|
}) {
|
|
3220
4087
|
const services = useChatServices();
|
|
3221
|
-
(0,
|
|
4088
|
+
(0, import_react18.useEffect)(() => {
|
|
3222
4089
|
if (!services) {
|
|
3223
4090
|
console.warn(
|
|
3224
4091
|
"[@pactor-app/chat] Chat \u672A\u68C0\u6D4B\u5230 ChatServicesProvider\uFF1A\u8BF7\u5728\u5E94\u7528\u6839\u90E8\u4EE5 <ChatServicesProvider> \u6CE8\u5165 transport \u7B49\u670D\u52A1"
|
|
@@ -3226,10 +4093,10 @@ function Chat({
|
|
|
3226
4093
|
}
|
|
3227
4094
|
}, [services]);
|
|
3228
4095
|
if (!services) {
|
|
3229
|
-
return /* @__PURE__ */ (0,
|
|
4096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pactor-chat-notice", role: "note", children: "\u672A\u914D\u7F6E\u804A\u5929\u670D\u52A1\uFF1A\u8BF7\u5728 Chat \u5916\u5C42\u4F7F\u7528 ChatServicesProvider \u6CE8\u5165 transport \u7B49\u670D\u52A1\u540E\u91CD\u8BD5\u3002" });
|
|
3230
4097
|
}
|
|
3231
4098
|
const sidebarSlot = resolveSlot(sidebar);
|
|
3232
|
-
const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0,
|
|
4099
|
+
const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3233
4100
|
ChatSidebarMenu,
|
|
3234
4101
|
{
|
|
3235
4102
|
menu,
|
|
@@ -3237,7 +4104,7 @@ function Chat({
|
|
|
3237
4104
|
onMenuSelect
|
|
3238
4105
|
}
|
|
3239
4106
|
) : void 0);
|
|
3240
|
-
return /* @__PURE__ */ (0,
|
|
4107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3241
4108
|
ChatComposition,
|
|
3242
4109
|
{
|
|
3243
4110
|
services,
|
|
@@ -3248,9 +4115,14 @@ function Chat({
|
|
|
3248
4115
|
conversationId,
|
|
3249
4116
|
params,
|
|
3250
4117
|
className,
|
|
3251
|
-
showHeader
|
|
4118
|
+
showHeader,
|
|
3252
4119
|
header: resolveSlot(header),
|
|
3253
4120
|
headerExtra: resolveSlot(headerExtra) ?? services.headerExtra,
|
|
4121
|
+
toolbarStart: resolveSlot(toolbarStart),
|
|
4122
|
+
toolbarEnd: resolveSlot(toolbarEnd),
|
|
4123
|
+
composerFooter: resolveSlot(composerFooter),
|
|
4124
|
+
composerBottom: resolveSlot(composerBottom),
|
|
4125
|
+
hideToolbar,
|
|
3254
4126
|
headerActions,
|
|
3255
4127
|
editableTitle,
|
|
3256
4128
|
onExport,
|
|
@@ -3292,7 +4164,7 @@ function ChatDslAdapter({
|
|
|
3292
4164
|
onTitleChange,
|
|
3293
4165
|
...rest
|
|
3294
4166
|
}) {
|
|
3295
|
-
return /* @__PURE__ */ (0,
|
|
4167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3296
4168
|
Chat,
|
|
3297
4169
|
{
|
|
3298
4170
|
...rest,
|
|
@@ -3317,13 +4189,18 @@ function registerChatComponent(registry) {
|
|
|
3317
4189
|
}
|
|
3318
4190
|
registerChatShellComponent(registry);
|
|
3319
4191
|
}
|
|
4192
|
+
function createChatComponentRegistry() {
|
|
4193
|
+
const registry = (0, import_components12.createComponentRegistry)();
|
|
4194
|
+
registerChatComponent(registry);
|
|
4195
|
+
return registry;
|
|
4196
|
+
}
|
|
3320
4197
|
|
|
3321
4198
|
// src/view/ChatLayout.tsx
|
|
3322
|
-
var
|
|
4199
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3323
4200
|
function ChatLayout({ title, children }) {
|
|
3324
|
-
return /* @__PURE__ */ (0,
|
|
3325
|
-
/* @__PURE__ */ (0,
|
|
3326
|
-
/* @__PURE__ */ (0,
|
|
4201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "pactor-chat-layout", children: [
|
|
4202
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("header", { className: "pactor-chat-layout__header", children: title ?? "Chat" }),
|
|
4203
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("main", { className: "pactor-chat-layout__main", children })
|
|
3327
4204
|
] });
|
|
3328
4205
|
}
|
|
3329
4206
|
var CHAT_LAYOUT_TYPE = "chat";
|
|
@@ -3353,14 +4230,13 @@ function registerChatLayout(layoutRegistry) {
|
|
|
3353
4230
|
ConversationStore,
|
|
3354
4231
|
DEFAULT_CHAT_GREETING,
|
|
3355
4232
|
EmptyState,
|
|
3356
|
-
MENU_ICONS,
|
|
3357
|
-
MESSAGE_ACTION_ICONS,
|
|
3358
4233
|
MessageActions,
|
|
3359
4234
|
MessageBubble,
|
|
3360
4235
|
PartRenderer,
|
|
3361
4236
|
applyChatEvent,
|
|
3362
4237
|
buildChatScope,
|
|
3363
4238
|
collectMessageText,
|
|
4239
|
+
createChatComponentRegistry,
|
|
3364
4240
|
createChatId,
|
|
3365
4241
|
createChatRuntime,
|
|
3366
4242
|
createChatWorkspace,
|