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