@agentscope-ai/chat 1.1.70 → 1.1.71-beta.1781610744021
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/components/AgentScopeRuntimeWebUI/core/Chat/Input/index.tsx +38 -5
- package/components/AgentScopeRuntimeWebUI/core/Chat/InputQueue/Panel.tsx +82 -0
- package/components/AgentScopeRuntimeWebUI/core/Chat/InputQueue/__tests__/inputQueue.test.ts +112 -0
- package/components/AgentScopeRuntimeWebUI/core/Chat/InputQueue/index.ts +122 -0
- package/components/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.tsx +111 -4
- package/components/AgentScopeRuntimeWebUI/core/Chat/index.tsx +21 -3
- package/components/AgentScopeRuntimeWebUI/core/Chat/styles.tsx +68 -1
- package/components/AgentScopeRuntimeWebUI/core/ChatAnywhere/index.tsx +1 -1
- package/components/AgentScopeRuntimeWebUI/core/Context/ChatAnywhereI18nContext.tsx +14 -0
- package/components/AgentScopeRuntimeWebUI/starter/index.tsx +100 -14
- package/components/AgentScopeRuntimeWebUI/starterForMe/index.tsx +31 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/Input/index.d.ts +8 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/Input/index.js +36 -8
- package/lib/AgentScopeRuntimeWebUI/core/Chat/InputQueue/Panel.d.ts +9 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/InputQueue/Panel.js +78 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/InputQueue/index.d.ts +37 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/InputQueue/index.js +74 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.d.ts +7 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.js +204 -63
- package/lib/AgentScopeRuntimeWebUI/core/Chat/index.js +14 -2
- package/lib/AgentScopeRuntimeWebUI/core/Chat/styles.js +31 -1
- package/lib/AgentScopeRuntimeWebUI/core/Context/ChatAnywhereI18nContext.d.ts +11 -1
- package/lib/AgentScopeRuntimeWebUI/core/Context/ChatAnywhereI18nContext.js +12 -0
- package/lib/AgentScopeRuntimeWebUI/starter/index.js +144 -20
- package/lib/AgentScopeRuntimeWebUI/starterForMe/index.d.ts +1 -0
- package/lib/AgentScopeRuntimeWebUI/starterForMe/index.js +34 -0
- package/package.json +2 -1
- package/bin/starter_webui/README.md +0 -75
- package/bin/starter_webui/eslint.config.js +0 -28
- package/bin/starter_webui/index.html +0 -12
- package/bin/starter_webui/package.json +0 -34
- package/bin/starter_webui/src/App.tsx +0 -20
- package/bin/starter_webui/src/components/Chat/OptionsPanel/FormItem.tsx +0 -37
- package/bin/starter_webui/src/components/Chat/OptionsPanel/OptionsEditor.tsx +0 -160
- package/bin/starter_webui/src/components/Chat/OptionsPanel/defaultConfig.ts +0 -41
- package/bin/starter_webui/src/components/Chat/OptionsPanel/index.tsx +0 -27
- package/bin/starter_webui/src/components/Chat/index.tsx +0 -45
- package/bin/starter_webui/src/components/Chat/sessionApi/index.ts +0 -53
- package/bin/starter_webui/src/main.tsx +0 -9
- package/bin/starter_webui/src/vite-env.d.ts +0 -4
- package/bin/starter_webui/tsconfig.app.json +0 -24
- package/bin/starter_webui/tsconfig.json +0 -7
- package/bin/starter_webui/tsconfig.node.json +0 -22
- package/bin/starter_webui/vite.config.ts +0 -11
|
@@ -35,6 +35,13 @@ const messages = {
|
|
|
35
35
|
'common.saveSuccess': '保存成功',
|
|
36
36
|
'common.saveFailed': '保存失败',
|
|
37
37
|
|
|
38
|
+
// Queue 相关
|
|
39
|
+
'queue.title': '待发送队列',
|
|
40
|
+
'queue.clear': '清空队列',
|
|
41
|
+
'queue.retry': '重试发送',
|
|
42
|
+
'queue.failed': '发送失败',
|
|
43
|
+
'queue.attachmentOnly': '附件消息',
|
|
44
|
+
|
|
38
45
|
// Actions 相关
|
|
39
46
|
'actions.regenerate': '重新生成',
|
|
40
47
|
|
|
@@ -73,6 +80,13 @@ const messages = {
|
|
|
73
80
|
'common.saveSuccess': 'Saved successfully',
|
|
74
81
|
'common.saveFailed': 'Failed to save',
|
|
75
82
|
|
|
83
|
+
// Queue related
|
|
84
|
+
'queue.title': 'Queued inputs',
|
|
85
|
+
'queue.clear': 'Clear queue',
|
|
86
|
+
'queue.retry': 'Retry',
|
|
87
|
+
'queue.failed': 'Failed to send',
|
|
88
|
+
'queue.attachmentOnly': 'Attachment message',
|
|
89
|
+
|
|
76
90
|
// Actions related
|
|
77
91
|
'actions.regenerate': 'Regenerate',
|
|
78
92
|
|
|
@@ -1,11 +1,97 @@
|
|
|
1
|
-
import { AgentScopeRuntimeWebUI, IAgentScopeRuntimeWebUIRef
|
|
1
|
+
import { AgentScopeRuntimeWebUI, IAgentScopeRuntimeWebUIRef } from '@agentscope-ai/chat';
|
|
2
2
|
import OptionsPanel from './OptionsPanel';
|
|
3
3
|
import { useMemo, useRef } from 'react';
|
|
4
4
|
import defaultConfig from './OptionsPanel/defaultConfig';
|
|
5
5
|
import { useLocalStorageState } from 'ahooks';
|
|
6
|
-
import { Flex } from 'antd';
|
|
6
|
+
import { Button, Flex } from 'antd';
|
|
7
7
|
import MessageImport from './MessageImport';
|
|
8
8
|
|
|
9
|
+
const encoder = new TextEncoder();
|
|
10
|
+
|
|
11
|
+
const sleep = (ms: number) => new Promise(resolve => {
|
|
12
|
+
setTimeout(resolve, ms);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
function getLastUserText(input: any[] = []) {
|
|
16
|
+
const lastMessage = input[input.length - 1];
|
|
17
|
+
const content = lastMessage?.content || [];
|
|
18
|
+
return content
|
|
19
|
+
.filter((item: any) => item?.type === 'text')
|
|
20
|
+
.map((item: any) => item.text)
|
|
21
|
+
.join('\n');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function createMockQueueResponse(data: {
|
|
25
|
+
input?: any[];
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}) {
|
|
28
|
+
const userText = getLastUserText(data.input);
|
|
29
|
+
const messageId = `queue-demo-${Date.now()}`;
|
|
30
|
+
const chunks = [
|
|
31
|
+
{
|
|
32
|
+
object: 'message',
|
|
33
|
+
id: messageId,
|
|
34
|
+
role: 'assistant',
|
|
35
|
+
type: 'message',
|
|
36
|
+
status: 'in_progress',
|
|
37
|
+
content: [],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
object: 'content',
|
|
41
|
+
msg_id: messageId,
|
|
42
|
+
type: 'text',
|
|
43
|
+
status: 'in_progress',
|
|
44
|
+
delta: true,
|
|
45
|
+
text: `Received: ${userText || 'attachment message'}\n\n`,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
object: 'content',
|
|
49
|
+
msg_id: messageId,
|
|
50
|
+
type: 'text',
|
|
51
|
+
status: 'in_progress',
|
|
52
|
+
delta: true,
|
|
53
|
+
text: 'This mock response is intentionally slow, ',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
object: 'content',
|
|
57
|
+
msg_id: messageId,
|
|
58
|
+
type: 'text',
|
|
59
|
+
status: 'in_progress',
|
|
60
|
+
delta: true,
|
|
61
|
+
text: 'so later inputs can enter the queue.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
object: 'response',
|
|
65
|
+
id: messageId,
|
|
66
|
+
status: 'completed',
|
|
67
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
68
|
+
output: [],
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const stream = new ReadableStream({
|
|
73
|
+
async start(controller) {
|
|
74
|
+
for (const chunk of chunks) {
|
|
75
|
+
if (data.signal?.aborted) {
|
|
76
|
+
controller.close();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await sleep(700);
|
|
80
|
+
controller.enqueue(
|
|
81
|
+
encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
controller.close();
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return new Response(stream, {
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'text/event-stream',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
9
95
|
|
|
10
96
|
export default function () {
|
|
11
97
|
|
|
@@ -20,6 +106,16 @@ export default function () {
|
|
|
20
106
|
|
|
21
107
|
const options = useMemo(() => {
|
|
22
108
|
const rightHeader = <Flex gap={16}>
|
|
109
|
+
<Button size="small" onClick={() => {
|
|
110
|
+
chatRef.current?.input.submit({ query: 'Queue demo 1: slow response' });
|
|
111
|
+
window.setTimeout(() => {
|
|
112
|
+
chatRef.current?.input.submit({ query: 'Queue demo 2: queued while busy' });
|
|
113
|
+
}, 400);
|
|
114
|
+
window.setTimeout(() => {
|
|
115
|
+
chatRef.current?.input.submit({ query: 'Queue demo 3: sent after demo 2' });
|
|
116
|
+
}, 800);
|
|
117
|
+
}}>Queue demo</Button>
|
|
118
|
+
|
|
23
119
|
<OptionsPanel value={optionsConfig} onChange={v => {
|
|
24
120
|
setOptionsConfig(prev => ({
|
|
25
121
|
...prev,
|
|
@@ -40,17 +136,6 @@ export default function () {
|
|
|
40
136
|
},
|
|
41
137
|
sender: {
|
|
42
138
|
...optionsConfig.sender,
|
|
43
|
-
beforeUI: <ChatInput.BeforeUIContainer>
|
|
44
|
-
<Flex gap={6}>
|
|
45
|
-
{
|
|
46
|
-
optionsConfig.welcome.prompts.map(prompt => (
|
|
47
|
-
<a key={prompt.value} onClick={() => {
|
|
48
|
-
chatRef.current?.input.submit({ query: prompt.value });
|
|
49
|
-
}}>{prompt.value}</a>
|
|
50
|
-
))
|
|
51
|
-
}
|
|
52
|
-
</Flex>
|
|
53
|
-
</ChatInput.BeforeUIContainer>,
|
|
54
139
|
attachments: optionsConfig.sender.attachments ? {
|
|
55
140
|
customRequest(options) {
|
|
56
141
|
// 模拟上传进度
|
|
@@ -71,6 +156,7 @@ export default function () {
|
|
|
71
156
|
},
|
|
72
157
|
api: {
|
|
73
158
|
...optionsConfig.api,
|
|
159
|
+
...(!optionsConfig.api.baseURL ? { fetch: createMockQueueResponse } : {}),
|
|
74
160
|
cancel: (data) => {
|
|
75
161
|
console.log('cancel', data);
|
|
76
162
|
},
|
|
@@ -87,4 +173,4 @@ export default function () {
|
|
|
87
173
|
options={options}
|
|
88
174
|
/>
|
|
89
175
|
</div>;
|
|
90
|
-
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AgentScopeRuntimeWebUI } from '@agentscope-ai/chat';
|
|
2
|
+
|
|
3
|
+
export default function Page() {
|
|
4
|
+
return (
|
|
5
|
+
<div style={{ height: '100dvh' }}>
|
|
6
|
+
<AgentScopeRuntimeWebUI
|
|
7
|
+
options={{
|
|
8
|
+
api: {
|
|
9
|
+
baseURL: '/api/runtime/chat',
|
|
10
|
+
token: 'your-token',
|
|
11
|
+
},
|
|
12
|
+
session: {
|
|
13
|
+
multiple: true,
|
|
14
|
+
},
|
|
15
|
+
theme: {
|
|
16
|
+
locale: 'en',
|
|
17
|
+
colorPrimary: '#615CED',
|
|
18
|
+
},
|
|
19
|
+
sender: {
|
|
20
|
+
placeholder: 'Ask something',
|
|
21
|
+
maxLength: 10000,
|
|
22
|
+
},
|
|
23
|
+
welcome: {
|
|
24
|
+
greeting: 'Hello, how can I help you today?',
|
|
25
|
+
prompts: [{ value: 'What can you do?' }],
|
|
26
|
+
},
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { IAgentScopeRuntimeWebUIInputData } from "../../../..";
|
|
2
|
+
import type { QueuedInputItem } from "../InputQueue";
|
|
2
3
|
export interface InputProps {
|
|
3
4
|
onCancel: () => void;
|
|
4
5
|
onSubmit: (data: IAgentScopeRuntimeWebUIInputData) => void;
|
|
6
|
+
queue?: {
|
|
7
|
+
items: QueuedInputItem[];
|
|
8
|
+
onEnqueue: (data: IAgentScopeRuntimeWebUIInputData) => void;
|
|
9
|
+
onRemove: (id: string) => void;
|
|
10
|
+
onClear: () => void;
|
|
11
|
+
onRetry: (id: string) => void;
|
|
12
|
+
};
|
|
5
13
|
}
|
|
6
14
|
export default function Input(props: InputProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -14,10 +14,12 @@ import { useChatAnywhereOptions } from "../../Context/ChatAnywhereOptionsContext
|
|
|
14
14
|
import { useGetState } from 'ahooks';
|
|
15
15
|
import { useChatAnywhereInput } from "../../Context/ChatAnywhereInputContext";
|
|
16
16
|
import useAttachments from "./useAttachments";
|
|
17
|
+
import InputQueuePanel from "../InputQueue/Panel";
|
|
18
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
19
|
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
20
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
21
|
export default function Input(props) {
|
|
22
|
+
var _props$queue4, _props$queue5;
|
|
21
23
|
var _useGetState = useGetState(''),
|
|
22
24
|
_useGetState2 = _slicedToArray(_useGetState, 3),
|
|
23
25
|
content = _useGetState2[0],
|
|
@@ -55,7 +57,8 @@ export default function Input(props) {
|
|
|
55
57
|
uploadIconButton = _useAttachments.uploadIconButton,
|
|
56
58
|
uploadFileListHeader = _useAttachments.uploadFileListHeader;
|
|
57
59
|
var handleSubmit = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
58
|
-
var
|
|
60
|
+
var _props$queue;
|
|
61
|
+
var next, fileList, data, _props$queue2;
|
|
59
62
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
60
63
|
while (1) switch (_context.prev = _context.next) {
|
|
61
64
|
case 0:
|
|
@@ -73,26 +76,51 @@ export default function Input(props) {
|
|
|
73
76
|
var _i$response;
|
|
74
77
|
return (_i$response = i.response) === null || _i$response === void 0 ? void 0 : _i$response.url;
|
|
75
78
|
});
|
|
76
|
-
|
|
79
|
+
data = {
|
|
77
80
|
query: getContent(),
|
|
78
81
|
fileList: fileList
|
|
79
|
-
}
|
|
82
|
+
};
|
|
83
|
+
if (inputContext.loading || (_props$queue = props.queue) !== null && _props$queue !== void 0 && _props$queue.items.length) {
|
|
84
|
+
(_props$queue2 = props.queue) === null || _props$queue2 === void 0 || _props$queue2.onEnqueue(data);
|
|
85
|
+
} else {
|
|
86
|
+
props.onSubmit(data);
|
|
87
|
+
}
|
|
80
88
|
setContent('');
|
|
81
|
-
setFileList
|
|
82
|
-
case
|
|
89
|
+
setFileList === null || setFileList === void 0 || setFileList([]);
|
|
90
|
+
case 10:
|
|
83
91
|
case "end":
|
|
84
92
|
return _context.stop();
|
|
85
93
|
}
|
|
86
94
|
}, _callee);
|
|
87
|
-
})), []);
|
|
95
|
+
})), [beforeSubmit, getContent, getFileList, inputContext.loading, props.onSubmit, props.queue, setContent, setFileList]);
|
|
96
|
+
var handleKeyDownCapture = useCallback(function (event) {
|
|
97
|
+
var _event$nativeEvent, _props$queue3;
|
|
98
|
+
if (event.key !== 'Enter' || event.shiftKey) return;
|
|
99
|
+
if ((_event$nativeEvent = event.nativeEvent) !== null && _event$nativeEvent !== void 0 && _event$nativeEvent.isComposing) return;
|
|
100
|
+
if (!inputContext.loading && !((_props$queue3 = props.queue) !== null && _props$queue3 !== void 0 && _props$queue3.items.length)) return;
|
|
101
|
+
var fileList = ((getFileList === null || getFileList === void 0 ? void 0 : getFileList()) || []).filter(function (i) {
|
|
102
|
+
var _i$response2;
|
|
103
|
+
return (_i$response2 = i.response) === null || _i$response2 === void 0 ? void 0 : _i$response2.url;
|
|
104
|
+
});
|
|
105
|
+
if (!getContent().trim() && fileList.length === 0) return;
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
event.stopPropagation();
|
|
108
|
+
void handleSubmit();
|
|
109
|
+
}, [getContent, getFileList, handleSubmit, inputContext.loading, (_props$queue4 = props.queue) === null || _props$queue4 === void 0 ? void 0 : _props$queue4.items.length]);
|
|
88
110
|
var handleCancel = useCallback(function () {
|
|
89
111
|
props.onCancel();
|
|
90
112
|
}, []);
|
|
91
113
|
return /*#__PURE__*/_jsxs("div", {
|
|
92
114
|
className: prefixCls,
|
|
115
|
+
onKeyDownCapture: handleKeyDownCapture,
|
|
93
116
|
children: [/*#__PURE__*/_jsxs("div", {
|
|
94
117
|
className: "".concat(prefixCls, "-wrapper"),
|
|
95
|
-
children: [beforeUI, /*#__PURE__*/_jsx(
|
|
118
|
+
children: [beforeUI, (_props$queue5 = props.queue) !== null && _props$queue5 !== void 0 && _props$queue5.items.length ? /*#__PURE__*/_jsx(InputQueuePanel, {
|
|
119
|
+
items: props.queue.items,
|
|
120
|
+
onRemove: props.queue.onRemove,
|
|
121
|
+
onClear: props.queue.onClear,
|
|
122
|
+
onRetry: props.queue.onRetry
|
|
123
|
+
}) : null, /*#__PURE__*/_jsx(ChatInput, {
|
|
96
124
|
loading: inputContext.loading,
|
|
97
125
|
disabled: inputContext.disabled,
|
|
98
126
|
placeholder: placeholder,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { QueuedInputItem } from './index';
|
|
2
|
+
interface InputQueuePanelProps {
|
|
3
|
+
items: QueuedInputItem[];
|
|
4
|
+
onRemove: (id: string) => void;
|
|
5
|
+
onClear: () => void;
|
|
6
|
+
onRetry: (id: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export default function InputQueuePanel(props: InputQueuePanelProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { IconButton } from '@agentscope-ai/design';
|
|
2
|
+
import { SparkClearLine, SparkDeleteLine, SparkRefreshLine } from '@agentscope-ai/icons';
|
|
3
|
+
import { Tooltip } from 'antd';
|
|
4
|
+
import { useProviderContext } from "../../../..";
|
|
5
|
+
import { useTranslation } from "../../Context/ChatAnywhereI18nContext";
|
|
6
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
export default function InputQueuePanel(props) {
|
|
9
|
+
var items = props.items,
|
|
10
|
+
onRemove = props.onRemove,
|
|
11
|
+
onClear = props.onClear,
|
|
12
|
+
onRetry = props.onRetry;
|
|
13
|
+
var prefixCls = useProviderContext().getPrefixCls('chat-anywhere-input-queue');
|
|
14
|
+
var _useTranslation = useTranslation(),
|
|
15
|
+
t = _useTranslation.t;
|
|
16
|
+
var tr = function tr(key) {
|
|
17
|
+
return (t === null || t === void 0 ? void 0 : t(key)) || key;
|
|
18
|
+
};
|
|
19
|
+
if (!items.length) return null;
|
|
20
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
21
|
+
className: prefixCls,
|
|
22
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
23
|
+
className: "".concat(prefixCls, "-header"),
|
|
24
|
+
children: [/*#__PURE__*/_jsxs("span", {
|
|
25
|
+
children: [tr('queue.title'), " (", items.length, ")"]
|
|
26
|
+
}), /*#__PURE__*/_jsx(Tooltip, {
|
|
27
|
+
title: tr('queue.clear'),
|
|
28
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
29
|
+
size: "small",
|
|
30
|
+
bordered: false,
|
|
31
|
+
icon: /*#__PURE__*/_jsx(SparkClearLine, {}),
|
|
32
|
+
onClick: onClear
|
|
33
|
+
})
|
|
34
|
+
})]
|
|
35
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
36
|
+
className: "".concat(prefixCls, "-list"),
|
|
37
|
+
children: items.map(function (item, index) {
|
|
38
|
+
var failed = item.status === 'failed';
|
|
39
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
40
|
+
className: "".concat(prefixCls, "-item"),
|
|
41
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
42
|
+
className: "".concat(prefixCls, "-index"),
|
|
43
|
+
children: index + 1
|
|
44
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
45
|
+
className: "".concat(prefixCls, "-content"),
|
|
46
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
47
|
+
className: "".concat(prefixCls, "-text"),
|
|
48
|
+
children: item.data.query || tr('queue.attachmentOnly')
|
|
49
|
+
}), failed ? /*#__PURE__*/_jsx("div", {
|
|
50
|
+
className: "".concat(prefixCls, "-error"),
|
|
51
|
+
children: item.errorMessage || tr('queue.failed')
|
|
52
|
+
}) : null]
|
|
53
|
+
}), failed ? /*#__PURE__*/_jsx(Tooltip, {
|
|
54
|
+
title: tr('queue.retry'),
|
|
55
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
56
|
+
size: "small",
|
|
57
|
+
bordered: false,
|
|
58
|
+
icon: /*#__PURE__*/_jsx(SparkRefreshLine, {}),
|
|
59
|
+
onClick: function onClick() {
|
|
60
|
+
return onRetry(item.id);
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}) : null, /*#__PURE__*/_jsx(Tooltip, {
|
|
64
|
+
title: tr('common.delete'),
|
|
65
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
66
|
+
size: "small",
|
|
67
|
+
bordered: false,
|
|
68
|
+
icon: /*#__PURE__*/_jsx(SparkDeleteLine, {}),
|
|
69
|
+
onClick: function onClick() {
|
|
70
|
+
return onRemove(item.id);
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
})]
|
|
74
|
+
}, item.id);
|
|
75
|
+
})
|
|
76
|
+
})]
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { IAgentScopeRuntimeWebUIInputData } from '../../types';
|
|
2
|
+
export type QueuedInputStatus = 'pending' | 'failed';
|
|
3
|
+
export interface QueuedInputItem {
|
|
4
|
+
id: string;
|
|
5
|
+
data: IAgentScopeRuntimeWebUIInputData;
|
|
6
|
+
status: QueuedInputStatus;
|
|
7
|
+
retryCount: number;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
createdAt: number;
|
|
10
|
+
}
|
|
11
|
+
export interface EnqueueQueuedInputResult {
|
|
12
|
+
queue: QueuedInputItem[];
|
|
13
|
+
item?: QueuedInputItem;
|
|
14
|
+
reason?: 'full';
|
|
15
|
+
}
|
|
16
|
+
export declare const MAX_INPUT_QUEUE_SIZE = 50;
|
|
17
|
+
export declare function createQueuedInputItem(data: IAgentScopeRuntimeWebUIInputData, options?: {
|
|
18
|
+
id?: string;
|
|
19
|
+
now?: number;
|
|
20
|
+
}): QueuedInputItem;
|
|
21
|
+
export declare function enqueueQueuedInput(queue: QueuedInputItem[], data: IAgentScopeRuntimeWebUIInputData, options?: {
|
|
22
|
+
maxSize?: number;
|
|
23
|
+
id?: string;
|
|
24
|
+
now?: number;
|
|
25
|
+
}): EnqueueQueuedInputResult;
|
|
26
|
+
export declare function dequeueNextQueuedInput(queue: QueuedInputItem[]): {
|
|
27
|
+
item?: QueuedInputItem;
|
|
28
|
+
queue: QueuedInputItem[];
|
|
29
|
+
};
|
|
30
|
+
export declare function removeQueuedInput(queue: QueuedInputItem[], id: string): QueuedInputItem[];
|
|
31
|
+
export declare function retryQueuedInput(queue: QueuedInputItem[], id: string): QueuedInputItem[];
|
|
32
|
+
export declare function restoreFailedQueuedInput(queue: QueuedInputItem[], item: QueuedInputItem, error?: unknown): QueuedInputItem[];
|
|
33
|
+
export declare function canSubmitDirectly(options: {
|
|
34
|
+
loading: boolean | string;
|
|
35
|
+
queueLength: number;
|
|
36
|
+
draining: boolean;
|
|
37
|
+
}): boolean;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
8
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
11
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
12
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
13
|
+
export var MAX_INPUT_QUEUE_SIZE = 50;
|
|
14
|
+
var queueId = 0;
|
|
15
|
+
export function createQueuedInputItem(data, options) {
|
|
16
|
+
var _options$now;
|
|
17
|
+
return {
|
|
18
|
+
id: (options === null || options === void 0 ? void 0 : options.id) || "input-queue-".concat(Date.now().toString(36), "-").concat((++queueId).toString(36)),
|
|
19
|
+
data: data,
|
|
20
|
+
status: 'pending',
|
|
21
|
+
retryCount: 0,
|
|
22
|
+
createdAt: (_options$now = options === null || options === void 0 ? void 0 : options.now) !== null && _options$now !== void 0 ? _options$now : Date.now()
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function enqueueQueuedInput(queue, data, options) {
|
|
26
|
+
var _options$maxSize;
|
|
27
|
+
var maxSize = (_options$maxSize = options === null || options === void 0 ? void 0 : options.maxSize) !== null && _options$maxSize !== void 0 ? _options$maxSize : MAX_INPUT_QUEUE_SIZE;
|
|
28
|
+
if (queue.length >= maxSize) {
|
|
29
|
+
return {
|
|
30
|
+
queue: queue,
|
|
31
|
+
reason: 'full'
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
var item = createQueuedInputItem(data, options);
|
|
35
|
+
return {
|
|
36
|
+
queue: [].concat(_toConsumableArray(queue), [item]),
|
|
37
|
+
item: item
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function dequeueNextQueuedInput(queue) {
|
|
41
|
+
var next = queue[0];
|
|
42
|
+
if (!next || next.status !== 'pending') {
|
|
43
|
+
return {
|
|
44
|
+
queue: queue
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
item: next,
|
|
49
|
+
queue: queue.slice(1)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function removeQueuedInput(queue, id) {
|
|
53
|
+
return queue.filter(function (item) {
|
|
54
|
+
return item.id !== id;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export function retryQueuedInput(queue, id) {
|
|
58
|
+
return queue.map(function (item) {
|
|
59
|
+
return item.id === id ? _objectSpread(_objectSpread({}, item), {}, {
|
|
60
|
+
status: 'pending',
|
|
61
|
+
errorMessage: undefined
|
|
62
|
+
}) : item;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function restoreFailedQueuedInput(queue, item, error) {
|
|
66
|
+
return [_objectSpread(_objectSpread({}, item), {}, {
|
|
67
|
+
status: 'failed',
|
|
68
|
+
retryCount: item.retryCount + 1,
|
|
69
|
+
errorMessage: error instanceof Error ? error.message : String(error || '')
|
|
70
|
+
})].concat(_toConsumableArray(queue));
|
|
71
|
+
}
|
|
72
|
+
export function canSubmitDirectly(options) {
|
|
73
|
+
return !options.loading && options.queueLength === 0 && !options.draining;
|
|
74
|
+
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { InputProps } from "../Input";
|
|
2
|
+
import { type QueuedInputItem } from "../InputQueue";
|
|
1
3
|
/**
|
|
2
4
|
* Chat controller hook — coordinates all chat-related operations.
|
|
3
5
|
*/
|
|
4
6
|
export default function useChatController(): {
|
|
5
7
|
handleSubmit: (data: import("../../../..").IAgentScopeRuntimeWebUIInputData) => void;
|
|
6
8
|
handleCancel: () => void;
|
|
9
|
+
inputQueue: QueuedInputItem[];
|
|
10
|
+
enqueueQueuedInput: (data: Parameters<InputProps['onSubmit']>[0]) => void;
|
|
11
|
+
removeQueuedInput: (id: string) => void;
|
|
12
|
+
clearQueuedInputs: () => void;
|
|
13
|
+
retryQueuedInput: (id: string) => void;
|
|
7
14
|
};
|