@ray-js/t-agent-ui-ray 0.2.8-beta.1 → 0.2.8-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-zh_CN.md +337 -87
- package/README.md +916 -706
- package/dist/LowCodeCardRender/index.js +1 -0
- package/dist/MessageInput/MessageInputAIStream/index.js +2 -24
- package/dist/MessageInput/index.js +1 -0
- package/dist/MessageList/ScrollBottomView.d.ts +2 -2
- package/dist/PrivateImage/index.js +7 -10
- package/dist/contexts.d.ts +0 -1
- package/dist/hooks/context.d.ts +1 -1
- package/dist/hooks/useAttachmentInput.d.ts +1 -2
- package/dist/i18n/strings.js +1 -0
- package/dist/index.js +1 -0
- package/dist/renderOption.js +7 -6
- package/dist/tiles/BubbleTile/index.d.ts +15 -1
- package/dist/tiles/BubbleTile/index.js +60 -68
- package/dist/tiles/BubbleToolTile/audio-play.svg +1 -0
- package/dist/tiles/BubbleToolTile/audio-playing.svg +24 -0
- package/dist/tiles/BubbleToolTile/copy.svg +1 -0
- package/dist/tiles/BubbleToolTile/index.d.ts +10 -0
- package/dist/tiles/BubbleToolTile/index.js +63 -0
- package/dist/tiles/BubbleToolTile/index.less +46 -0
- package/dist/tiles/CardTile/index.d.ts +1 -1
- package/dist/tiles/DividerTile/index.d.ts +1 -1
- package/dist/tiles/OperateCardTile/Expand.d.ts +1 -1
- package/dist/tiles/TextTile/index.d.ts +1 -1
- package/dist/tiles/TimeTile/index.js +17 -16
- package/dist/tiles/TipTile/index.d.ts +1 -1
- package/dist/tiles/map.js +3 -3
- package/dist/tiles/types.d.ts +1 -1
- package/dist/utils/abort.js +1 -0
- package/dist/utils/createSharedStore.d.ts +2 -2
- package/dist/utils/getMessageContent.d.ts +11 -0
- package/dist/utils/getMessageContent.js +49 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +3 -1
- package/dist/utils/ttt.d.ts +1 -0
- package/dist/utils/ttt.js +24 -0
- package/package.json +5 -4
- package/dist/tiles/WorkflowTile/RollBack/index.d.ts +0 -5
- package/dist/tiles/WorkflowTile/RollBack/index.js +0 -27
- package/dist/tiles/WorkflowTile/RollBack/index.less +0 -20
- package/dist/tiles/WorkflowTile/RollBack/workflow-rollback.png +0 -0
- package/dist/tiles/WorkflowTile/index.d.ts +0 -21
- package/dist/tiles/WorkflowTile/index.js +0 -32
- package/dist/tiles/WorkflowTile/index.less +0 -31
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# AI
|
|
1
|
+
# AI Assistant SDK
|
|
2
2
|
|
|
3
3
|
## Version Notes
|
|
4
4
|
|
|
5
|
-
**⚠️ Important
|
|
5
|
+
**⚠️ Important**: Starting from version 0.2.x, `@ray-js/t-agent-plugin-assistant` has been deprecated. Please use `@ray-js/t-agent-plugin-aistream` instead.
|
|
6
6
|
|
|
7
|
-
## Installation (
|
|
7
|
+
## Installation (Ray mini-program)
|
|
8
8
|
|
|
9
9
|
```shell
|
|
10
10
|
yarn add @ray-js/t-agent @ray-js/t-agent-plugin-aistream @ray-js/t-agent-ui-ray
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
>
|
|
13
|
+
> Make sure `@ray-js/t-agent`, `@ray-js/t-agent-plugin-aistream`, and `@ray-js/t-agent-ui-ray` are on the same version.
|
|
14
14
|
|
|
15
|
-
## Mini-
|
|
15
|
+
## Mini-program Kit Requirements
|
|
16
16
|
|
|
17
17
|
```json
|
|
18
18
|
{
|
|
@@ -22,12 +22,14 @@ yarn add @ray-js/t-agent @ray-js/t-agent-plugin-aistream @ray-js/t-agent-ui-ray
|
|
|
22
22
|
"DeviceKit": "4.6.1",
|
|
23
23
|
"HomeKit": "3.4.0",
|
|
24
24
|
"MiniKit": "3.12.1",
|
|
25
|
-
"AIStreamKit": "1.
|
|
25
|
+
"AIStreamKit": "1.3.2"
|
|
26
26
|
},
|
|
27
27
|
"baseversion": "2.21.10"
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
> When using MCP features, `AIStreamKit` needs to be `2.2.1` or above.
|
|
32
|
+
|
|
31
33
|
## package.json Dependency Requirements
|
|
32
34
|
|
|
33
35
|
```json
|
|
@@ -50,7 +52,7 @@ yarn run miniapp
|
|
|
50
52
|
|
|
51
53
|
## Usage Example
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
Build a chat page with Ray UI.
|
|
54
56
|
|
|
55
57
|

|
|
56
58
|
|
|
@@ -59,59 +61,70 @@ Implementing a chat page using ray UI
|
|
|
59
61
|
import React from 'react';
|
|
60
62
|
import { View } from '@ray-js/components';
|
|
61
63
|
import { createChatAgent, withDebug, withUI } from '@ray-js/t-agent';
|
|
62
|
-
import {
|
|
64
|
+
import {
|
|
65
|
+
ChatContainer,
|
|
66
|
+
defaultRenderOptions,
|
|
67
|
+
MessageInput,
|
|
68
|
+
MessageList,
|
|
69
|
+
MessageActionBar,
|
|
70
|
+
} from '@ray-js/t-agent-ui-ray';
|
|
63
71
|
import { withAIStream, withBuildIn } from '@ray-js/t-agent-plugin-aistream';
|
|
64
72
|
|
|
65
73
|
const createAgent = () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
const agent = createChatAgent(
|
|
75
|
+
withUI(),
|
|
76
|
+
withAIStream({
|
|
77
|
+
earlyStart: true,
|
|
78
|
+
agentId: 'your-agent-id',
|
|
79
|
+
tokenOptions: {
|
|
80
|
+
api: 'm.life.ai.agent.token.get',
|
|
81
|
+
version: '1.0',
|
|
82
|
+
extParams: {
|
|
83
|
+
dialogueMode: 1,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
withDebug(),
|
|
88
|
+
withBuildIn()
|
|
89
|
+
);
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
92
|
+
if (type === 'start-event') {
|
|
93
|
+
result.userData = {
|
|
94
|
+
sessionAttributes: {
|
|
95
|
+
'custom.param': {
|
|
96
|
+
'custom.app.scene': {
|
|
97
|
+
value: 'chat-page',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
});
|
|
81
104
|
|
|
82
|
-
|
|
83
|
-
onChatStart(async result => {
|
|
84
|
-
const hello = createMessage({
|
|
85
|
-
role: 'assistant',
|
|
86
|
-
});
|
|
105
|
+
const { onChatStart, createMessage } = agent;
|
|
87
106
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
await hello.persist();
|
|
107
|
+
onChatStart(async result => {
|
|
108
|
+
const hello = createMessage({
|
|
109
|
+
role: 'assistant',
|
|
92
110
|
});
|
|
93
111
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
});
|
|
112
|
+
hello.bubble.setText('Hello, world!');
|
|
113
|
+
result.messages.push(hello);
|
|
114
|
+
await hello.persist();
|
|
115
|
+
});
|
|
99
116
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.error('Agent creation failed:', error);
|
|
107
|
-
throw error;
|
|
108
|
-
}
|
|
117
|
+
return agent;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const renderOptions = {
|
|
121
|
+
...defaultRenderOptions,
|
|
109
122
|
};
|
|
110
123
|
|
|
111
124
|
export default function ChatPage() {
|
|
112
125
|
return (
|
|
113
126
|
<View style={{ height: '100vh' }}>
|
|
114
|
-
<ChatContainer createAgent={createAgent}>
|
|
127
|
+
<ChatContainer createAgent={createAgent} renderOptions={renderOptions}>
|
|
115
128
|
<MessageList />
|
|
116
129
|
<MessageInput />
|
|
117
130
|
<MessageActionBar />
|
|
@@ -123,46 +136,47 @@ export default function ChatPage() {
|
|
|
123
136
|
|
|
124
137
|
# t-agent
|
|
125
138
|
|
|
126
|
-
The t-agent package
|
|
139
|
+
The t-agent package is a conversational assistant SDK written in TypeScript, used to build conversational agents. It supports a plugin mechanism that lets you extend the agent's capabilities.
|
|
140
|
+
This is a pure SDK package that contains no UI components, so it can be paired with any UI framework.
|
|
127
141
|
|
|
128
142
|
## Basic Concepts
|
|
129
143
|
|
|
130
|
-

|
|
131
145
|
|
|
132
|
-
### ChatAgent
|
|
146
|
+
### ChatAgent
|
|
133
147
|
|
|
134
|
-
The core class
|
|
148
|
+
The core class of the conversational agent. It manages the conversation lifecycle, message creation, message persistence, and so on. It supports plugins and a hook mechanism to extend the agent's capabilities.
|
|
135
149
|
|
|
136
|
-
|
|
150
|
+
Use `createChatAgent` to create a ChatAgent instance:
|
|
137
151
|
|
|
138
152
|
```tsx
|
|
139
153
|
import { createChatAgent } from '@ray-js/t-agent';
|
|
140
154
|
const createAgent = () => {
|
|
141
|
-
/* Apply plugins in the createChatAgent
|
|
155
|
+
/* Apply plugins in the createChatAgent arguments. Note that plugin order matters. */
|
|
142
156
|
const agent = createChatAgent();
|
|
143
157
|
|
|
144
158
|
return agent;
|
|
145
159
|
};
|
|
146
160
|
```
|
|
147
161
|
|
|
148
|
-
|
|
162
|
+
Main properties:
|
|
149
163
|
|
|
150
|
-
- `agent.session` ChatSession container
|
|
151
|
-
- `agent.plugins`
|
|
164
|
+
- `agent.session` — the ChatSession container, used to store session-related data
|
|
165
|
+
- `agent.plugins` — after applying plugins, the plugins' methods and hooks are stored here
|
|
152
166
|
|
|
153
|
-
|
|
167
|
+
Main methods:
|
|
154
168
|
|
|
155
|
-
- `agent.start()`
|
|
156
|
-
- `agent.dispose()`
|
|
157
|
-
- `agent.pushInputBlocks(blocks, signal)`
|
|
158
|
-
- `agent.createMessage(data)`
|
|
159
|
-
- `agent.emitTileEvent(tileId: string, payload: any)`
|
|
160
|
-
- `agent.removeMessage(messageId: string)`
|
|
161
|
-
- `agent.flushStreamToShow(message: ChatMessage, response: StreamResponse, composer: ComposeHandler)`
|
|
169
|
+
- `agent.start()` — start
|
|
170
|
+
- `agent.dispose()` — release
|
|
171
|
+
- `agent.pushInputBlocks(blocks, signal)` — push message blocks into the ChatAgent from the outside, used when a user sends a message to the AI
|
|
172
|
+
- `agent.createMessage(data)` — create a message bound to the current agent
|
|
173
|
+
- `agent.emitTileEvent(tileId: string, payload: any)` — emit a tile event
|
|
174
|
+
- `agent.removeMessage(messageId: string)` — remove a message
|
|
175
|
+
- `agent.flushStreamToShow(message: ChatMessage, response: StreamResponse, composer: ComposeHandler)` — stream-update a message
|
|
162
176
|
|
|
163
|
-
###
|
|
177
|
+
### Hook Mechanism
|
|
164
178
|
|
|
165
|
-
ChatAgent
|
|
179
|
+
ChatAgent only defines a runtime framework and data structures; the actual behavior is implemented through the hook mechanism. The hook mechanism is an event-driven programming model — you register callback functions to implement the agent's behavior.
|
|
166
180
|
|
|
167
181
|
```tsx
|
|
168
182
|
import { createChatAgent } from '@ray-js/t-agent';
|
|
@@ -171,7 +185,7 @@ const createAgent = () => {
|
|
|
171
185
|
|
|
172
186
|
const { onChatStart } = agent;
|
|
173
187
|
|
|
174
|
-
// onChatStart
|
|
188
|
+
// The onChatStart hook fires when the conversation starts
|
|
175
189
|
onChatStart(result => {
|
|
176
190
|
console.log('Chat start', result);
|
|
177
191
|
});
|
|
@@ -181,67 +195,68 @@ const createAgent = () => {
|
|
|
181
195
|
|
|
182
196
|
#### Hook Execution Order
|
|
183
197
|
|
|
184
|
-
Hooks
|
|
198
|
+
Hooks execute in the following order:
|
|
185
199
|
|
|
186
200
|
```
|
|
187
201
|
onAgentStart → onChatStart/onChatResume → onMessageListInit → onInputBlocksPush
|
|
188
202
|
```
|
|
189
203
|
|
|
190
|
-
ChatAgent's
|
|
191
|
-
|
|
192
|
-
- `agent.onAgentStart`
|
|
193
|
-
- `agent.onChatStart`
|
|
194
|
-
- `result.messages`
|
|
195
|
-
- `agent.onChatResume`
|
|
196
|
-
- `result.messages`
|
|
197
|
-
- `agent.onMessageListInit`
|
|
198
|
-
- `result.messages`
|
|
199
|
-
- `agent.onInputBlocksPush`
|
|
200
|
-
- `blocks`
|
|
201
|
-
- `signal`
|
|
202
|
-
- `agent.onMessageChange`
|
|
203
|
-
- `type`
|
|
204
|
-
- `message`
|
|
205
|
-
- `agent.onMessagePersist`
|
|
206
|
-
- `payload`
|
|
207
|
-
- `message`
|
|
208
|
-
- `agent.onTileEvent`
|
|
209
|
-
- `tile`
|
|
210
|
-
- `payload`
|
|
211
|
-
- `agent.onAgentDispose`
|
|
212
|
-
- `agent.onUserAbort`
|
|
213
|
-
- `reason`
|
|
214
|
-
- `agent.onError`
|
|
215
|
-
- `error`
|
|
216
|
-
|
|
217
|
-
These hooks accept a callback
|
|
218
|
-
|
|
219
|
-
### ChatSession
|
|
204
|
+
ChatAgent's main hooks and parameters:
|
|
205
|
+
|
|
206
|
+
- `agent.onAgentStart` — initialize the agent
|
|
207
|
+
- `agent.onChatStart` — fires when the conversation starts
|
|
208
|
+
- `result.messages` — used to initialize the message list
|
|
209
|
+
- `agent.onChatResume` — fires when the conversation resumes
|
|
210
|
+
- `result.messages` — the already-restored message list
|
|
211
|
+
- `agent.onMessageListInit` — fires when the message list is initialized, after chat start or resume
|
|
212
|
+
- `result.messages` — the message list used for rendering; it's the same list as the message in the two hooks above
|
|
213
|
+
- `agent.onInputBlocksPush` — fires when message blocks are pushed
|
|
214
|
+
- `blocks` — the input message blocks
|
|
215
|
+
- `signal` — the abort signal
|
|
216
|
+
- `agent.onMessageChange` — fires when a message changes
|
|
217
|
+
- `type` — the change type: `show`, `update`, `remove`
|
|
218
|
+
- `message` — the changed message
|
|
219
|
+
- `agent.onMessagePersist` — fires when a message is persisted
|
|
220
|
+
- `payload` — persistence-related parameters
|
|
221
|
+
- `message` — the target message being persisted
|
|
222
|
+
- `agent.onTileEvent` — fires when a tile event occurs
|
|
223
|
+
- `tile` — the tile that triggered the event
|
|
224
|
+
- `payload` — the event payload
|
|
225
|
+
- `agent.onAgentDispose` — fires when the agent is released
|
|
226
|
+
- `agent.onUserAbort` — fires when the user aborts
|
|
227
|
+
- `reason` — the abort reason
|
|
228
|
+
- `agent.onError` — fires on error
|
|
229
|
+
- `error` — the error object
|
|
230
|
+
|
|
231
|
+
These hooks all accept a callback function as their argument and call it when triggered. The callback can be synchronous or asynchronous, and its return value does not affect the result. If you need to change the result, modify the callback's `result` argument, or modify the tile or message object.
|
|
232
|
+
|
|
233
|
+
### ChatSession
|
|
234
|
+
|
|
235
|
+
ChatSession stores the message list of the conversation with the agent, context data, and so on. It is created together with the ChatAgent.
|
|
236
|
+
|
|
237
|
+
Main properties:
|
|
238
|
+
|
|
239
|
+
- `session.messages` — the message list
|
|
240
|
+
- `session.sessionId` — the session id
|
|
241
|
+
- `session.isNewChat` — whether this is a new conversation, used to distinguish a new chat (`onChatStart`) from a resumed chat (`onChatResume`)
|
|
242
|
+
|
|
243
|
+
Main methods:
|
|
244
|
+
|
|
245
|
+
- `session.set` — set session data, can be any type
|
|
246
|
+
- `session.get` — get session data
|
|
247
|
+
- `session.getData` — get session data in object form
|
|
248
|
+
- `session.getLatestMessage` — get the last message
|
|
220
249
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
Main Properties:
|
|
224
|
-
|
|
225
|
-
- `session.messages` List of messages
|
|
226
|
-
- `session.sessionId` Unique session ID
|
|
227
|
-
- `session.isNewChat` To distinguish fresh or ongoing chats
|
|
228
|
-
|
|
229
|
-
Principal Methods:
|
|
230
|
-
|
|
231
|
-
- `session.set` Assign session data (any type)
|
|
232
|
-
- `session.get` Retrieve session data
|
|
233
|
-
- `session.getData` Fetch session data in object format
|
|
234
|
-
- `session.getLatestMessage` Access the latest message
|
|
235
|
-
|
|
236
|
-
Hook:
|
|
250
|
+
Hooks:
|
|
237
251
|
|
|
238
|
-
- `session.onChange`
|
|
252
|
+
- `session.onChange` — register a callback for session data changes
|
|
239
253
|
|
|
240
|
-
### ChatMessage
|
|
254
|
+
### ChatMessage
|
|
241
255
|
|
|
242
|
-
|
|
256
|
+
ChatMessage is an abstraction of a conversation message, used to store the message's content, status, and other information. It also provides a set of convenient methods for operating on messages.
|
|
257
|
+
A single ChatMessage can contain multiple ChatTiles, used to display different content.
|
|
243
258
|
|
|
244
|
-
|
|
259
|
+
Use the `createMessage` method to create a message:
|
|
245
260
|
|
|
246
261
|
```tsx
|
|
247
262
|
const createAgent = () => {
|
|
@@ -249,13 +264,14 @@ const createAgent = () => {
|
|
|
249
264
|
|
|
250
265
|
const { createMessage, onChatStart } = agent;
|
|
251
266
|
|
|
252
|
-
//
|
|
267
|
+
// When the chat initializes, send a message
|
|
253
268
|
onChatStart(async result => {
|
|
269
|
+
// Create a message sent by the assistant
|
|
254
270
|
const message = createMessage({
|
|
255
271
|
role: 'assistant',
|
|
256
272
|
});
|
|
257
273
|
|
|
258
|
-
//
|
|
274
|
+
// Access message.bubble to quickly create a text bubble
|
|
259
275
|
message.bubble.setText('Hello!');
|
|
260
276
|
result.messages.push(message);
|
|
261
277
|
});
|
|
@@ -264,43 +280,43 @@ const createAgent = () => {
|
|
|
264
280
|
};
|
|
265
281
|
```
|
|
266
282
|
|
|
267
|
-
|
|
283
|
+
Main properties:
|
|
268
284
|
|
|
269
|
-
- `message.id`
|
|
270
|
-
- `message.role`
|
|
271
|
-
- `message.tiles`
|
|
272
|
-
- `message.status`
|
|
273
|
-
- `message.meta`
|
|
274
|
-
- `message.isShow`
|
|
275
|
-
- `message.bubble`
|
|
285
|
+
- `message.id` — the message id
|
|
286
|
+
- `message.role` — the message role, either `assistant` or `user`
|
|
287
|
+
- `message.tiles` — the message's tile list
|
|
288
|
+
- `message.status` — the message status, a `ChatMessageStatus` enum, which can be `START`, `UPDATING`, `FINISH`, etc.
|
|
289
|
+
- `message.meta` — extra data attached to the message
|
|
290
|
+
- `message.isShow` — whether the message has been displayed in the UI
|
|
291
|
+
- `message.bubble` — a shortcut to the message's bubble tile
|
|
276
292
|
|
|
277
|
-
|
|
293
|
+
Main methods:
|
|
278
294
|
|
|
279
|
-
- `message.show`
|
|
280
|
-
- `message.update`
|
|
281
|
-
- `message.remove`
|
|
282
|
-
- `message.persist`
|
|
283
|
-
- `message.addTile`
|
|
284
|
-
- `message.removeTile`
|
|
285
|
-
- `message.setTilesLocked`
|
|
286
|
-
- `message.set`
|
|
287
|
-
- `message.setMetaValue`
|
|
288
|
-
- `message.deleteMetaValue`
|
|
289
|
-
- `message.setMeta`
|
|
290
|
-
- `message.findTileByType`
|
|
295
|
+
- `message.show` — display the message in the UI
|
|
296
|
+
- `message.update` — update the current message's state in the UI
|
|
297
|
+
- `message.remove` — remove the current message from the UI
|
|
298
|
+
- `message.persist` — persist the message
|
|
299
|
+
- `message.addTile` — add a tile
|
|
300
|
+
- `message.removeTile` — remove a tile
|
|
301
|
+
- `message.setTilesLocked` — set the locked state of all tiles
|
|
302
|
+
- `message.set` — set message properties
|
|
303
|
+
- `message.setMetaValue` — set a meta property by key-value
|
|
304
|
+
- `message.deleteMetaValue` — delete a meta property
|
|
305
|
+
- `message.setMeta` — set the meta object directly
|
|
306
|
+
- `message.findTileByType` — find a tile by tile type
|
|
291
307
|
|
|
292
|
-
#### ChatTile
|
|
308
|
+
#### ChatTile
|
|
293
309
|
|
|
294
|
-
|
|
310
|
+
ChatTile is a block within a conversation message, used to display different content inside a message, such as text, images, cards, etc.
|
|
295
311
|
|
|
296
|
-
|
|
312
|
+
Use the `addTile` method to add a tile to a message:
|
|
297
313
|
|
|
298
314
|
```tsx
|
|
299
315
|
const message = createMessage({
|
|
300
316
|
role: 'assistant',
|
|
301
317
|
});
|
|
302
318
|
|
|
303
|
-
//
|
|
319
|
+
// Add an image tile
|
|
304
320
|
message.addTile('image', {
|
|
305
321
|
src: '/image.jpg',
|
|
306
322
|
});
|
|
@@ -308,27 +324,27 @@ message.addTile('image', {
|
|
|
308
324
|
await message.show();
|
|
309
325
|
```
|
|
310
326
|
|
|
311
|
-
|
|
327
|
+
ChatTile's main properties:
|
|
312
328
|
|
|
313
|
-
- `tile.id`
|
|
314
|
-
- `tile.type`
|
|
315
|
-
- `tile.data`
|
|
316
|
-
- `tile.children`
|
|
317
|
-
- `tile.locked`
|
|
318
|
-
- `tile.fallback`
|
|
319
|
-
- `tile.message`
|
|
329
|
+
- `tile.id` — the tile id
|
|
330
|
+
- `tile.type` — the tile type
|
|
331
|
+
- `tile.data` — the tile data
|
|
332
|
+
- `tile.children` — the tile's child tiles
|
|
333
|
+
- `tile.locked` — whether the tile is locked
|
|
334
|
+
- `tile.fallback` — fallback content when the tile cannot be displayed
|
|
335
|
+
- `tile.message` — the message the tile belongs to
|
|
320
336
|
|
|
321
|
-
|
|
337
|
+
ChatTile's main methods:
|
|
322
338
|
|
|
323
|
-
- `tile.update`
|
|
324
|
-
- `tile.show`
|
|
325
|
-
- `tile.setLocked`
|
|
326
|
-
- `tile.addTile`
|
|
327
|
-
- `tile.setData`
|
|
328
|
-
- `tile.setFallback`
|
|
329
|
-
- `tile.findByType`
|
|
339
|
+
- `tile.update` — a shortcut for `tile.message.update`
|
|
340
|
+
- `tile.show` — a shortcut for `tile.message.show`
|
|
341
|
+
- `tile.setLocked` — set the tile's locked state
|
|
342
|
+
- `tile.addTile` — add a child tile
|
|
343
|
+
- `tile.setData` — set the tile's data
|
|
344
|
+
- `tile.setFallback` — set the tile's fallback content
|
|
345
|
+
- `tile.findByType` — find a child tile by tile type
|
|
330
346
|
|
|
331
|
-
|
|
347
|
+
`message.bubble` is a shortcut — simply accessing it quickly adds a bubble tile to the current message:
|
|
332
348
|
|
|
333
349
|
```tsx
|
|
334
350
|
const message = createMessage({
|
|
@@ -336,125 +352,125 @@ const message = createMessage({
|
|
|
336
352
|
});
|
|
337
353
|
|
|
338
354
|
message.bubble.setText('Hello, world!');
|
|
339
|
-
//
|
|
355
|
+
// is equivalent to
|
|
340
356
|
message.addTile('bubble', {}).addTile('text', { text: 'Hello, world!' });
|
|
341
357
|
|
|
342
358
|
await message.show();
|
|
343
359
|
```
|
|
344
360
|
|
|
345
|
-
For bubble messages,
|
|
361
|
+
For bubble messages, in addition to the basic tile methods, some extra properties and methods are provided:
|
|
346
362
|
|
|
347
|
-
- `message.bubble.text`
|
|
348
|
-
- `message.bubble.setText`
|
|
349
|
-
- `message.bubble.isMarkdown`
|
|
350
|
-
- `message.bubble.setIsMarkdown`
|
|
351
|
-
- `message.bubble.status`
|
|
352
|
-
- `message.bubble.setStatus`
|
|
353
|
-
- `message.bubble.info`
|
|
354
|
-
- `message.bubble.setInfo`
|
|
355
|
-
- `message.bubble.initWithInputBlocks`
|
|
363
|
+
- `message.bubble.text` — property, read the bubble text
|
|
364
|
+
- `message.bubble.setText` — method, set the bubble text
|
|
365
|
+
- `message.bubble.isMarkdown` — property, whether the content is in markdown format
|
|
366
|
+
- `message.bubble.setIsMarkdown` — method, set whether the content is markdown
|
|
367
|
+
- `message.bubble.status` — property, the bubble status (`BubbleTileStatus`)
|
|
368
|
+
- `message.bubble.setStatus` — method, set the bubble status
|
|
369
|
+
- `message.bubble.info` — property, the bubble info
|
|
370
|
+
- `message.bubble.setInfo` — method, set the bubble info
|
|
371
|
+
- `message.bubble.initWithInputBlocks` — method, initialize the bubble with input blocks
|
|
356
372
|
|
|
357
|
-
**Bubble messages support long
|
|
373
|
+
**Bubble messages support long-press operations**, such as copy and delete. Animations are also shown while the message is loading and updating.
|
|
358
374
|
|
|
359
|
-
Bubble messages support the following long
|
|
375
|
+
Bubble messages support the following long-press operations:
|
|
360
376
|
|
|
361
|
-
- Copy:
|
|
362
|
-
- Delete:
|
|
377
|
+
- Copy: copy the message text content
|
|
378
|
+
- Delete: delete the current message
|
|
363
379
|
|
|
364
380
|
### Lifecycle
|
|
365
381
|
|
|
366
|
-
ChatAgent
|
|
382
|
+
ChatAgent triggers different hooks at different stages. Developers can register hooks to implement custom behavior. The sequence diagram below shows the ChatAgent lifecycle.
|
|
367
383
|
|
|
368
384
|
```mermaid
|
|
369
385
|
sequenceDiagram
|
|
370
386
|
participant AI as Backend(AI)
|
|
371
387
|
participant A as ChatAgent
|
|
372
|
-
participant UI as UI
|
|
388
|
+
participant UI as UI
|
|
373
389
|
actor User as User
|
|
374
390
|
|
|
375
|
-
User ->> UI: Open chat
|
|
376
|
-
UI ->> UI: Create
|
|
377
|
-
UI ->> A: agent.start()
|
|
391
|
+
User ->> UI: Open the chat UI
|
|
392
|
+
UI ->> UI: Create the agent object `agent`
|
|
393
|
+
UI ->> A: agent.start() starts the agent
|
|
378
394
|
rect rgba(255,255,0,0.1)
|
|
379
395
|
note over A: Hook: onAgentStart
|
|
380
|
-
A ->> AI: Check
|
|
396
|
+
A ->> AI: Check whether it's a new session
|
|
381
397
|
AI ->> A: Return
|
|
382
398
|
end
|
|
383
|
-
alt
|
|
399
|
+
alt New session
|
|
384
400
|
A ->> AI: Start a new session
|
|
385
401
|
note over A: Hook: onChatStart
|
|
386
|
-
else
|
|
402
|
+
else Resume session
|
|
387
403
|
A ->> AI: Read session history
|
|
388
404
|
AI ->> A: Return history messages
|
|
389
405
|
note over A: Hook: onChatResume
|
|
390
406
|
end
|
|
391
407
|
rect rgba(255,255,0,0.1)
|
|
392
408
|
note over A: Hook: onMessageListInit
|
|
393
|
-
A ->> UI: Assemble messages to display
|
|
409
|
+
A ->> UI: Assemble the messages to display
|
|
394
410
|
UI ->> User: Display messages
|
|
395
411
|
end
|
|
396
412
|
opt Conversation
|
|
397
|
-
User ->> UI:
|
|
413
|
+
User ->> UI: Type and send a message
|
|
398
414
|
UI ->> A: agent.pushInputBlocks()
|
|
399
415
|
rect rgba(255,255,0,0.1)
|
|
400
416
|
note over A: Hook: onInputBlocksPush
|
|
401
|
-
A ->> A: Create
|
|
417
|
+
A ->> A: Create message object `msg`<br/>set msg to the user's input text<br/>msg.show()
|
|
402
418
|
note over A: Hook: onMessageChange show
|
|
403
|
-
A -->> UI: Update
|
|
404
|
-
UI -->> User: Display new message
|
|
405
|
-
A ->> A: Create
|
|
419
|
+
A -->> UI: Update the UI
|
|
420
|
+
UI -->> User: Display the new message
|
|
421
|
+
A ->> A: Create message object `respMsg`<br/>set respMsg to loading<br/>respMsg.show()
|
|
406
422
|
note over A: Hook: onMessageChange show
|
|
407
|
-
A -->> UI: Update
|
|
408
|
-
UI -->> User: Display loading message
|
|
409
|
-
A ->> AI:
|
|
410
|
-
AI ->> A: Return message stream
|
|
423
|
+
A -->> UI: Update the UI
|
|
424
|
+
UI -->> User: Display the loading response message
|
|
425
|
+
A ->> AI: Call the AI
|
|
426
|
+
AI ->> A: Return the message stream
|
|
411
427
|
loop Streaming messages
|
|
412
428
|
AI ->> A: Message packet
|
|
413
429
|
A ->> A: Update respMsg data<br/>respMsg.update()
|
|
414
430
|
note over A: Hook: onMessageChange update
|
|
415
|
-
A -->> UI: Update
|
|
416
|
-
UI -->> User:
|
|
431
|
+
A -->> UI: Update the UI
|
|
432
|
+
UI -->> User: Stream text / show cards
|
|
417
433
|
end
|
|
418
434
|
end
|
|
419
435
|
end
|
|
420
436
|
|
|
421
|
-
opt Operate message action
|
|
422
|
-
User ->> UI: Select option
|
|
437
|
+
opt Operate on a message action point (single-select example)
|
|
438
|
+
User ->> UI: Select an option
|
|
423
439
|
UI ->> A: agent.emitTileEvent()
|
|
424
440
|
rect rgba(255,255,0,0.1)
|
|
425
441
|
note over A: Hook: onTileEvent
|
|
426
442
|
A ->> A: Set msg status<br/>msg.persist()
|
|
427
443
|
note over A: Hook: onMessagePersist
|
|
428
|
-
A ->> AI: Persist message
|
|
444
|
+
A ->> AI: Persist the message
|
|
429
445
|
AI ->> A: Return result
|
|
430
446
|
A ->> A: msg.update()
|
|
431
447
|
note over A: Hook: onMessageChange update
|
|
432
|
-
A ->> UI: Update
|
|
433
|
-
UI ->> User:
|
|
448
|
+
A ->> UI: Update the UI
|
|
449
|
+
UI ->> User: Dim the message, highlight the selection
|
|
434
450
|
end
|
|
435
451
|
end
|
|
436
|
-
opt Delete message
|
|
437
|
-
User ->> UI: Delete message
|
|
452
|
+
opt Delete a message
|
|
453
|
+
User ->> UI: Delete a message
|
|
438
454
|
UI ->> A: agent.removeMessage()
|
|
439
455
|
rect rgba(255,255,0,0.1)
|
|
440
456
|
A ->> A: msg.remove()
|
|
441
|
-
A ->> AI: Mark message deleted
|
|
457
|
+
A ->> AI: Mark the message as deleted
|
|
442
458
|
note over A: Hook: onMessageChange remove
|
|
443
|
-
A ->> UI: Update
|
|
444
|
-
UI ->> User:
|
|
459
|
+
A ->> UI: Update the UI
|
|
460
|
+
UI ->> User: The message disappears
|
|
445
461
|
end
|
|
446
462
|
end
|
|
447
463
|
```
|
|
448
464
|
|
|
449
465
|
### Plugin Mechanism
|
|
450
466
|
|
|
451
|
-
Plugins are implemented
|
|
467
|
+
Plugins are implemented on top of the hook mechanism above. Plugins can implement agent capabilities, such as integrating with an AI platform or providing a UI. Plugins can also expose methods and properties for developers to use.
|
|
452
468
|
|
|
453
469
|
```tsx
|
|
454
470
|
import { createChatAgent, withUI } from '@ray-js/t-agent';
|
|
455
471
|
const createAgent = () => {
|
|
456
472
|
const agent = createChatAgent(
|
|
457
|
-
withUI() // withUI plugin provides
|
|
473
|
+
withUI() // The withUI plugin provides some UI rendering methods
|
|
458
474
|
);
|
|
459
475
|
|
|
460
476
|
return agent;
|
|
@@ -468,7 +484,7 @@ const ScrollToBottom = () => {
|
|
|
468
484
|
const agent = useChatAgent();
|
|
469
485
|
|
|
470
486
|
const scroll = () => {
|
|
471
|
-
// Use
|
|
487
|
+
// Use a method exposed by a plugin
|
|
472
488
|
agent.plugins.ui.emitEvent('scrollToBottom', { animation: false });
|
|
473
489
|
};
|
|
474
490
|
|
|
@@ -478,12 +494,12 @@ const ScrollToBottom = () => {
|
|
|
478
494
|
|
|
479
495
|
#### Writing a Plugin
|
|
480
496
|
|
|
481
|
-
A plugin is a higher-order function that takes options and returns a function.
|
|
497
|
+
A plugin is a higher-order function that takes an options object and returns a function. That function receives a ChatAgent object, in which you can register hooks.
|
|
482
498
|
|
|
483
499
|
```tsx
|
|
484
500
|
import { ChatAgent, createHooks, Hookable } from '@ray-js/t-agent';
|
|
485
501
|
|
|
486
|
-
//
|
|
502
|
+
// Try a MyPlugin plugin
|
|
487
503
|
export type MyPlugin = GetChatPluginHandler<typeof withMyPlugin>;
|
|
488
504
|
|
|
489
505
|
export const withMyPlugin = (options: any) => {
|
|
@@ -495,11 +511,11 @@ export const withMyPlugin = (options: any) => {
|
|
|
495
511
|
|
|
496
512
|
onChatStart(async () => {
|
|
497
513
|
console.log('Chat start');
|
|
498
|
-
// Trigger plugin hook
|
|
514
|
+
// Trigger the plugin's hook
|
|
499
515
|
await hooks.callHook('onMyHook', 'Hello, world!');
|
|
500
516
|
});
|
|
501
517
|
|
|
502
|
-
// Expose plugin methods and hooks
|
|
518
|
+
// Expose the plugin's methods and hooks
|
|
503
519
|
return {
|
|
504
520
|
hooks,
|
|
505
521
|
myPlugin: {
|
|
@@ -518,7 +534,7 @@ export const withMyPlugin = (options: any) => {
|
|
|
518
534
|
```
|
|
519
535
|
|
|
520
536
|
```tsx
|
|
521
|
-
//
|
|
537
|
+
// Use the plugin
|
|
522
538
|
import { createChatAgent } from '@ray-js/t-agent';
|
|
523
539
|
|
|
524
540
|
const createAgent = () => {
|
|
@@ -527,10 +543,10 @@ const createAgent = () => {
|
|
|
527
543
|
withMyPlugin({})
|
|
528
544
|
);
|
|
529
545
|
|
|
530
|
-
// Call
|
|
546
|
+
// Call a method exposed by the plugin
|
|
531
547
|
agent.plugins.myPlugin.myMethod();
|
|
532
548
|
|
|
533
|
-
// Register plugin
|
|
549
|
+
// Register the plugin's hook
|
|
534
550
|
agent.plugins.myPlugin.onMyHook(msg => {
|
|
535
551
|
console.log(msg);
|
|
536
552
|
});
|
|
@@ -543,12 +559,12 @@ const createAgent = () => {
|
|
|
543
559
|
|
|
544
560
|
### withDebug
|
|
545
561
|
|
|
546
|
-
The withDebug plugin logs
|
|
562
|
+
The withDebug plugin prints logs to the console for convenient debugging.
|
|
547
563
|
|
|
548
564
|
```tsx
|
|
549
565
|
const agent = createChatAgent(
|
|
550
566
|
withDebug({
|
|
551
|
-
autoStart: true, // Whether to start automatically,
|
|
567
|
+
autoStart: true, // Whether to start automatically, defaults to true
|
|
552
568
|
})
|
|
553
569
|
);
|
|
554
570
|
|
|
@@ -561,72 +577,72 @@ agent.plugins.debug.stop();
|
|
|
561
577
|
|
|
562
578
|
### withUI
|
|
563
579
|
|
|
564
|
-
The withUI plugin provides default UI behaviors such as
|
|
580
|
+
The withUI plugin provides some default UI behaviors, such as displaying and deleting messages, and an event bus.
|
|
565
581
|
|
|
566
582
|
```tsx
|
|
567
583
|
const agent = createChatAgent(withUI());
|
|
568
584
|
|
|
569
|
-
agent.plugins.ui.emitter; //
|
|
585
|
+
agent.plugins.ui.emitter; // The event bus
|
|
570
586
|
|
|
571
587
|
// Scroll to bottom
|
|
572
588
|
agent.plugins.ui.emitEvent('scrollToBottom', { animation: false });
|
|
573
589
|
|
|
574
|
-
// Listen
|
|
590
|
+
// Listen for an event
|
|
575
591
|
const off = agent.plugins.ui.onEvent('scrollToBottom', payload => {
|
|
576
592
|
console.log('scroll to bottom', payload.animation);
|
|
577
593
|
});
|
|
578
594
|
|
|
579
|
-
//
|
|
595
|
+
// Stop listening
|
|
580
596
|
off();
|
|
581
597
|
```
|
|
582
598
|
|
|
583
|
-
The main events of the
|
|
599
|
+
The main events of the ui plugin are listed below; you can also freely register your own events:
|
|
584
600
|
|
|
585
|
-
- `messageListInit
|
|
586
|
-
- `payload.messages: ChatMessageObject[]
|
|
587
|
-
- `messageChange
|
|
588
|
-
- `payload.type: 'show' | 'update' | 'remove'
|
|
589
|
-
- `payload.message: ChatMessageObject
|
|
590
|
-
- `scrollToBottom
|
|
591
|
-
- `payload.animation: boolean
|
|
592
|
-
- `sendMessage
|
|
593
|
-
- `payload.blocks: InputBlock[]
|
|
594
|
-
- `setInputBlocks
|
|
595
|
-
- `payload.blocks: InputBlock[]
|
|
596
|
-
- `sessionChange
|
|
597
|
-
- `payload.key: string
|
|
598
|
-
- `payload.value: any
|
|
599
|
-
- `payload.oldValue: any
|
|
601
|
+
- `messageListInit` — initialize the message list
|
|
602
|
+
- `payload.messages: ChatMessageObject[]` — the message list
|
|
603
|
+
- `messageChange` — message changed
|
|
604
|
+
- `payload.type: 'show' | 'update' | 'remove'` — the change type
|
|
605
|
+
- `payload.message: ChatMessageObject` — the message
|
|
606
|
+
- `scrollToBottom` — scroll to bottom
|
|
607
|
+
- `payload.animation: boolean` — whether to animate
|
|
608
|
+
- `sendMessage` — send a message, triggering a UI update
|
|
609
|
+
- `payload.blocks: InputBlock[]` — the input blocks
|
|
610
|
+
- `setInputBlocks` — set input blocks into the MessageInput field
|
|
611
|
+
- `payload.blocks: InputBlock[]` — the input blocks
|
|
612
|
+
- `sessionChange` — session data changed
|
|
613
|
+
- `payload.key: string` — the session data key
|
|
614
|
+
- `payload.value: any` — the session data value
|
|
615
|
+
- `payload.oldValue: any` — the old session data value
|
|
600
616
|
|
|
601
|
-
|
|
617
|
+
UI plugin enhancements (new in 0.2.x):
|
|
602
618
|
|
|
603
|
-
|
|
619
|
+
In 0.2.x, the withUI plugin adds a hook mechanism that lets developers customize message-feedback and history-clearing behaviors:
|
|
604
620
|
|
|
605
|
-
**Message
|
|
621
|
+
**Message feedback hook**:
|
|
606
622
|
|
|
607
|
-
- `agent.plugins.ui.hook('onMessageFeedback', async context => {})`
|
|
608
|
-
- `context.payload.messageId: string`
|
|
609
|
-
- `context.payload.rate: 'like' | 'unlike'`
|
|
610
|
-
- `context.payload.content?: string`
|
|
611
|
-
- `context.result: { success: boolean }`
|
|
623
|
+
- `agent.plugins.ui.hook('onMessageFeedback', async context => {})` — register a message feedback hook
|
|
624
|
+
- `context.payload.messageId: string` — the message ID
|
|
625
|
+
- `context.payload.rate: 'like' | 'unlike'` — the feedback type
|
|
626
|
+
- `context.payload.content?: string` — feedback content (optional)
|
|
627
|
+
- `context.result: { success: boolean }` — the return result; you must set whether it succeeded
|
|
612
628
|
|
|
613
|
-
**Clear
|
|
629
|
+
**Clear history hook**:
|
|
614
630
|
|
|
615
|
-
- `agent.plugins.ui.hook('onClearHistory', async context => {})`
|
|
616
|
-
- `context.payload: any`
|
|
617
|
-
- `context.result: { success: boolean }`
|
|
631
|
+
- `agent.plugins.ui.hook('onClearHistory', async context => {})` — register a clear-history hook
|
|
632
|
+
- `context.payload: any` — the clear-history parameters
|
|
633
|
+
- `context.result: { success: boolean }` — the return result; you must set whether it succeeded
|
|
618
634
|
|
|
619
|
-
**Calling
|
|
635
|
+
**Calling hooks**:
|
|
620
636
|
|
|
621
|
-
- `agent.plugins.ui.callHook('onMessageFeedback', payload)`
|
|
622
|
-
- `agent.plugins.ui.callHook('onClearHistory', payload)`
|
|
637
|
+
- `agent.plugins.ui.callHook('onMessageFeedback', payload)` — call the message feedback hook
|
|
638
|
+
- `agent.plugins.ui.callHook('onClearHistory', payload)` — call the clear-history hook
|
|
623
639
|
|
|
624
640
|
Usage example:
|
|
625
641
|
|
|
626
642
|
```tsx
|
|
627
643
|
const agent = createChatAgent(withUI(), withAIStream({ agentId: 'your-agent-id' }));
|
|
628
644
|
|
|
629
|
-
// Register message feedback
|
|
645
|
+
// Register message feedback handling
|
|
630
646
|
agent.plugins.ui.hook('onMessageFeedback', async context => {
|
|
631
647
|
const { messageId, rate, content } = context.payload;
|
|
632
648
|
try {
|
|
@@ -638,7 +654,7 @@ agent.plugins.ui.hook('onMessageFeedback', async context => {
|
|
|
638
654
|
}
|
|
639
655
|
});
|
|
640
656
|
|
|
641
|
-
// Register clear
|
|
657
|
+
// Register clear-history handling
|
|
642
658
|
agent.plugins.ui.hook('onClearHistory', async context => {
|
|
643
659
|
try {
|
|
644
660
|
// Call your API to clear history
|
|
@@ -650,14 +666,15 @@ agent.plugins.ui.hook('onClearHistory', async context => {
|
|
|
650
666
|
});
|
|
651
667
|
```
|
|
652
668
|
|
|
653
|
-
> Note: `ChatMessageObject` here is a message object, not
|
|
654
|
-
> It contains
|
|
669
|
+
> Note: `ChatMessageObject` here is a message object, not the `ChatMessage` type.
|
|
670
|
+
> It contains some of the message's properties and methods. This is to avoid modifying the message object in the UI layer, which would cause inconsistency with the message object in the ChatAgent.
|
|
671
|
+
> Modifications to message objects should always be done in the ChatAgent.
|
|
655
672
|
|
|
656
|
-
##
|
|
673
|
+
## Bundled utils
|
|
657
674
|
|
|
658
675
|
### getLogger(prefix: string): Logger
|
|
659
676
|
|
|
660
|
-
Create a logger for
|
|
677
|
+
Create a logger for printing logs.
|
|
661
678
|
|
|
662
679
|
```tsx
|
|
663
680
|
import { getLogger } from '@ray-js/t-agent';
|
|
@@ -667,31 +684,31 @@ logger.debug('Hello, world!');
|
|
|
667
684
|
|
|
668
685
|
### Emitter
|
|
669
686
|
|
|
670
|
-
Emitter is an event bus
|
|
687
|
+
Emitter is an event bus used to register and dispatch events.
|
|
671
688
|
|
|
672
689
|
```tsx
|
|
673
690
|
import { Emitter, EmitterEvent } from '@ray-js/t-agent';
|
|
674
691
|
const emitter = new Emitter();
|
|
675
692
|
|
|
676
|
-
// Register event
|
|
693
|
+
// Register an event
|
|
677
694
|
const cb = event => console.log('detail', event.detail);
|
|
678
695
|
emitter.addEventListener('event', cb);
|
|
679
696
|
|
|
680
|
-
//
|
|
697
|
+
// Dispatch an event
|
|
681
698
|
emitter.dispatchEvent(new EmitterEvent('event', { detail: 'Hello, world!' }));
|
|
682
699
|
|
|
683
|
-
// Remove event
|
|
700
|
+
// Remove the event
|
|
684
701
|
emitter.removeEventListener('event', cb);
|
|
685
702
|
```
|
|
686
703
|
|
|
687
704
|
### StreamResponse
|
|
688
705
|
|
|
689
|
-
StreamResponse is a streaming response object
|
|
706
|
+
StreamResponse is a streaming response object used to handle streaming messages.
|
|
690
707
|
|
|
691
708
|
```tsx
|
|
692
709
|
import { StreamResponse } from '@ray-js/t-agent';
|
|
693
710
|
|
|
694
|
-
const partStream = await getPartStream(); //
|
|
711
|
+
const partStream = await getPartStream(); // Get the stream data
|
|
695
712
|
const response = new StreamResponse(partStream);
|
|
696
713
|
|
|
697
714
|
const parts = response.parts();
|
|
@@ -702,15 +719,15 @@ for await (const part of parts) {
|
|
|
702
719
|
|
|
703
720
|
### createHooks, Hookable
|
|
704
721
|
|
|
705
|
-
|
|
722
|
+
See the `hookable` npm package.
|
|
706
723
|
|
|
707
724
|
### isAbortError
|
|
708
725
|
|
|
709
|
-
Determine
|
|
726
|
+
Determine whether an error is an abort error.
|
|
710
727
|
|
|
711
728
|
### safeParseJSON
|
|
712
729
|
|
|
713
|
-
Safely parse JSON
|
|
730
|
+
Safely parse a JSON string. Returns `undefined` if parsing fails.
|
|
714
731
|
|
|
715
732
|
```tsx
|
|
716
733
|
import { safeParseJSON } from '@ray-js/t-agent';
|
|
@@ -722,7 +739,7 @@ console.log(obj.a); // 1
|
|
|
722
739
|
|
|
723
740
|
# t-agent-plugin-aistream
|
|
724
741
|
|
|
725
|
-
t-agent-plugin-aistream is a plugin
|
|
742
|
+
t-agent-plugin-aistream is a plugin that integrates with the mini-program AI agent platform, providing the ability to connect to it.
|
|
726
743
|
|
|
727
744
|
## Installation
|
|
728
745
|
|
|
@@ -738,10 +755,9 @@ import { withAIStream, withBuildIn } from '@ray-js/t-agent-plugin-aistream';
|
|
|
738
755
|
|
|
739
756
|
const createAgent = () => {
|
|
740
757
|
const agent = createChatAgent(
|
|
741
|
-
withUI(), //
|
|
758
|
+
withUI(), // The withUI plugin is generally required
|
|
742
759
|
withAIStream({
|
|
743
|
-
|
|
744
|
-
agentId: 'your-agent-id', // Provide your agent ID
|
|
760
|
+
agentId: 'your-agent-id', // Enter your agent ID
|
|
745
761
|
}),
|
|
746
762
|
withBuildIn()
|
|
747
763
|
);
|
|
@@ -752,76 +768,160 @@ const createAgent = () => {
|
|
|
752
768
|
|
|
753
769
|
## Included Plugins
|
|
754
770
|
|
|
755
|
-
### withAIStream
|
|
771
|
+
### withAIStream
|
|
756
772
|
|
|
757
|
-
|
|
773
|
+
Provides the ability to integrate with the mini-program AI agent platform.
|
|
758
774
|
|
|
759
775
|
Parameters:
|
|
760
776
|
|
|
761
|
-
- `agentId`
|
|
762
|
-
- `clientType`
|
|
763
|
-
- `deviceId`
|
|
764
|
-
- `wireInput`
|
|
765
|
-
- `historySize`
|
|
766
|
-
- `indexId`
|
|
767
|
-
- `homeId`
|
|
768
|
-
- `earlyStart`
|
|
769
|
-
- `eventIdPrefix`
|
|
770
|
-
- `tokenOptions`
|
|
771
|
-
- `api` API
|
|
772
|
-
- `version`
|
|
773
|
-
- `extParams`
|
|
774
|
-
- `createChatHistoryStore`
|
|
777
|
+
- `agentId` — the agent ID (required)
|
|
778
|
+
- `clientType` — the client type, defaults to APP (2)
|
|
779
|
+
- `deviceId` — the device ID, required when `clientType` is DEVICE (1)
|
|
780
|
+
- `wireInput` — whether to pass input blocks to the agent, defaults to true. When set to false, you need to write your own `onInputBlocksPush` hook to handle input blocks
|
|
781
|
+
- `historySize` — the history message size, defaults to 1000
|
|
782
|
+
- `indexId` — the index ID, defaults to `'default'`
|
|
783
|
+
- `homeId` — the home ID; defaults to the current home if not provided
|
|
784
|
+
- `earlyStart` — whether to establish the connection during the `onAgentStart` stage
|
|
785
|
+
- `eventIdPrefix` — the eventId prefix, used to make cloud-side debugging and log tracing easier
|
|
786
|
+
- `tokenOptions` — parameters for getting the agent token
|
|
787
|
+
- `api` — the API name
|
|
788
|
+
- `version` — the API version
|
|
789
|
+
- `extParams` — extra parameters
|
|
790
|
+
- `createChatHistoryStore` — a custom message storage function
|
|
775
791
|
|
|
776
792
|
Methods:
|
|
777
793
|
|
|
778
|
-
- `agent.plugins.aiStream.send(blocks, signal, userData)`
|
|
779
|
-
- `blocks`
|
|
780
|
-
- `signal`
|
|
781
|
-
- `userData`
|
|
782
|
-
- `agent.plugins.aiStream.chat(blocks, signal, options)`
|
|
783
|
-
- `blocks`
|
|
784
|
-
- `signal`
|
|
785
|
-
- `options.sendBy`
|
|
786
|
-
- `options.responseBy`
|
|
787
|
-
- `options.userData`
|
|
788
|
-
- `agent.plugins.aiStream.
|
|
794
|
+
- `agent.plugins.aiStream.send(blocks, signal, userData)` — send a message to the agent
|
|
795
|
+
- `blocks` — the input block array
|
|
796
|
+
- `signal` — an optional AbortSignal used to abort the request
|
|
797
|
+
- `userData` — optional user data attached to the sent message
|
|
798
|
+
- `agent.plugins.aiStream.chat(blocks, signal, options)` — send a message to the agent and generate a question ChatMessage and an AI answer ChatMessage, with streaming updates
|
|
799
|
+
- `blocks` — the input block array
|
|
800
|
+
- `signal` — an optional AbortSignal
|
|
801
|
+
- `options.sendBy` — the sender role, defaults to `'user'`
|
|
802
|
+
- `options.responseBy` — the responder role, defaults to `'assistant'`
|
|
803
|
+
- `options.userData` — optional user data
|
|
804
|
+
- `agent.plugins.aiStream.removeMessage(message)` — delete a history message
|
|
805
|
+
- `agent.plugins.aiStream.clearAllMessages()` — clear all messages of the current session and the local history
|
|
806
|
+
- `agent.plugins.aiStream.getChatId()` — get the current session's chatId, returns `Promise<string>`
|
|
789
807
|
|
|
790
808
|
Hooks:
|
|
791
809
|
|
|
792
|
-
- `onMessageParse`
|
|
793
|
-
- `msgItem`
|
|
794
|
-
- `result.messages`
|
|
795
|
-
- `onChatMessageSent`
|
|
796
|
-
- `userMessage`
|
|
797
|
-
- `respMessage` AI's response message
|
|
798
|
-
- `onTextCompose`
|
|
799
|
-
- `respMsg`
|
|
800
|
-
- `status`
|
|
801
|
-
- `result.text`
|
|
802
|
-
- `onSkillCompose`
|
|
803
|
-
- `skill`
|
|
804
|
-
- `respMsg`
|
|
805
|
-
- `result.messages`
|
|
806
|
-
- `onSkillsEnd`
|
|
807
|
-
- `skills`
|
|
808
|
-
- `respMsg`
|
|
809
|
-
- `result.messages`
|
|
810
|
-
- `onTTTAction`
|
|
811
|
-
- `tile`
|
|
812
|
-
- `result.action` TTTAction, can
|
|
813
|
-
- `onCardsReceived`
|
|
814
|
-
- `skills`
|
|
815
|
-
- `result.cards`
|
|
816
|
-
- `onUserDataRead` **(0.2.x
|
|
817
|
-
- `type`
|
|
818
|
-
- `'create-session'`
|
|
819
|
-
- `'start-event'`
|
|
820
|
-
- `data`
|
|
821
|
-
- `data.blocks`
|
|
822
|
-
- `result.userData`
|
|
823
|
-
|
|
824
|
-
|
|
810
|
+
- `onMessageParse` — fires when reading and parsing history messages; you can modify the message in this hook
|
|
811
|
+
- `msgItem` — the stored message object
|
|
812
|
+
- `result.messages` — the parsed message list
|
|
813
|
+
- `onChatMessageSent` — fires after the user message and response message are created
|
|
814
|
+
- `userMessage` — the message sent by the user
|
|
815
|
+
- `respMessage` — the AI's response message
|
|
816
|
+
- `onTextCompose` — fires when text data is received, used to handle text rendering
|
|
817
|
+
- `respMsg` — the response message
|
|
818
|
+
- `status` — the message status
|
|
819
|
+
- `result.text` — the text content, can be modified
|
|
820
|
+
- `onSkillCompose` — fires when skill data is received, used to handle skill rendering
|
|
821
|
+
- `skill` — the current skill data (`ReceivedTextSkillPacketBody`)
|
|
822
|
+
- `respMsg` — the response message
|
|
823
|
+
- `result.messages` — the message list
|
|
824
|
+
- `onSkillsEnd` — fires when all skills have been processed
|
|
825
|
+
- `skills` — the skill data list (`ReceivedTextSkillPacketBody[]`)
|
|
826
|
+
- `respMsg` — the response message
|
|
827
|
+
- `result.messages` — the message list
|
|
828
|
+
- `onTTTAction` — fires when a tile uses `sendAction`
|
|
829
|
+
- `tile` — the triggering tile
|
|
830
|
+
- `result.action` — the TTTAction, which can be modified to change the action to execute
|
|
831
|
+
- `onCardsReceived` — fires when card data is received
|
|
832
|
+
- `skills` — the skill data list (`ReceivedTextSkillPacketBody[]`)
|
|
833
|
+
- `result.cards` — the card list
|
|
834
|
+
- `onUserDataRead` **(new in 0.2.x)** — fires when custom user data needs to be read, used to pass extra context information to the AI platform
|
|
835
|
+
- `type` — the trigger type, either `'create-session'` or `'start-event'`
|
|
836
|
+
- `'create-session'` — fires when creating a session, only once
|
|
837
|
+
- `'start-event'` — fires each time a message is sent
|
|
838
|
+
- `data` — the context data
|
|
839
|
+
- `data.blocks` — when type is `'start-event'`, contains the input blocks of this send
|
|
840
|
+
- `result.userData` — the returned user data object, which is merged and sent to the AI platform
|
|
841
|
+
|
|
842
|
+
### withMCP
|
|
843
|
+
|
|
844
|
+
Provides the ability to expose MCP services, allowing the agent to call tools provided inside the mini-program — implementing operations such as controlling Bluetooth devices, calling custom APIs, and reading local files. To use it, you first need to enable "Device MCP" on the agent node. In addition, MCP tool names must start with `device.`.
|
|
845
|
+
|
|
846
|
+

|
|
847
|
+
|
|
848
|
+
**Prerequisites**:
|
|
849
|
+
|
|
850
|
+
- Must be used after `withAIStream`
|
|
851
|
+
- When using MCP features, `AIStreamKit` needs to be `2.2.1` or above
|
|
852
|
+
- `createServer` must return an `McpServer` synchronously
|
|
853
|
+
|
|
854
|
+
Parameters:
|
|
855
|
+
|
|
856
|
+
- `createServer(agent)` — create the MCP service instance
|
|
857
|
+
- `createContext(event, agent)` — optional, supplements context for each MCP request
|
|
858
|
+
|
|
859
|
+
**Usage example**:
|
|
860
|
+
|
|
861
|
+
```tsx
|
|
862
|
+
import { createChatAgent, withUI } from '@ray-js/t-agent';
|
|
863
|
+
import { McpServer, withAIStream, withMCP } from '@ray-js/t-agent-plugin-aistream';
|
|
864
|
+
|
|
865
|
+
const createAgent = () => {
|
|
866
|
+
const server = new McpServer({
|
|
867
|
+
name: 'demo-mcp',
|
|
868
|
+
version: '1.0.0',
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
server.registerTool(
|
|
872
|
+
'device.echo',
|
|
873
|
+
{
|
|
874
|
+
description: 'Echo back the input parameters',
|
|
875
|
+
inputSchema: {
|
|
876
|
+
type: 'object',
|
|
877
|
+
properties: {
|
|
878
|
+
text: { type: 'string' },
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
async (args, context) => {
|
|
883
|
+
return {
|
|
884
|
+
content: [
|
|
885
|
+
{
|
|
886
|
+
type: 'text',
|
|
887
|
+
text: JSON.stringify({
|
|
888
|
+
text: args.text,
|
|
889
|
+
sessionId: context.sessionId,
|
|
890
|
+
}),
|
|
891
|
+
},
|
|
892
|
+
],
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
return createChatAgent(
|
|
898
|
+
withUI(),
|
|
899
|
+
withAIStream({
|
|
900
|
+
agentId: 'your-agent-id',
|
|
901
|
+
}),
|
|
902
|
+
withMCP({
|
|
903
|
+
createServer: () => server,
|
|
904
|
+
createContext: event => ({
|
|
905
|
+
traceId: event.eventId,
|
|
906
|
+
}),
|
|
907
|
+
})
|
|
908
|
+
);
|
|
909
|
+
};
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Once enabled, the plugin will:
|
|
913
|
+
|
|
914
|
+
- Inject `sessionAttributes.deviceMcp` when creating a session
|
|
915
|
+
- Call the corresponding tool when an `MCP_CMD` event is received
|
|
916
|
+
- Return the tool execution result to AIStream in JSON-RPC response format
|
|
917
|
+
|
|
918
|
+
### Passing Custom Variables
|
|
919
|
+
|
|
920
|
+
In some cases you may need to pass custom variables into the agent as variables in the workflow. You need to configure the references to the custom variables in the workflow, and then pass them in from the mini-program:
|
|
921
|
+
|
|
922
|
+

|
|
923
|
+
|
|
924
|
+
**Passing custom variables from the mini-program**:
|
|
825
925
|
|
|
826
926
|
```tsx
|
|
827
927
|
const agent = createChatAgent(
|
|
@@ -834,10 +934,14 @@ const agent = createChatAgent(
|
|
|
834
934
|
agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
835
935
|
// Pass user information when creating a session
|
|
836
936
|
if (type === 'create-session') {
|
|
837
|
-
result.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
937
|
+
result.userData = {
|
|
938
|
+
sessionAttributes: {
|
|
939
|
+
'custom.param': {
|
|
940
|
+
'custom.app.test_me': {
|
|
941
|
+
// This is the parameter name configured to be received on the platform
|
|
942
|
+
value: `with value test me ${type} ${Date.now()}`,
|
|
943
|
+
},
|
|
944
|
+
},
|
|
841
945
|
},
|
|
842
946
|
};
|
|
843
947
|
return;
|
|
@@ -845,9 +949,13 @@ agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
|
845
949
|
// Pass dynamic context each time a message is sent
|
|
846
950
|
if (type === 'start-event') {
|
|
847
951
|
result.userData = {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
952
|
+
sessionAttributes: {
|
|
953
|
+
'custom.param': {
|
|
954
|
+
'custom.app.test_me': {
|
|
955
|
+
// This is the parameter name configured to be received on the platform
|
|
956
|
+
value: `with value test me ${type} ${Date.now()}`,
|
|
957
|
+
},
|
|
958
|
+
},
|
|
851
959
|
},
|
|
852
960
|
};
|
|
853
961
|
return;
|
|
@@ -855,18 +963,77 @@ agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
|
855
963
|
});
|
|
856
964
|
```
|
|
857
965
|
|
|
858
|
-
### withBuildIn
|
|
966
|
+
### withBuildIn
|
|
967
|
+
|
|
968
|
+
Provides some built-in features, such as smart home and knowledge base search.
|
|
969
|
+
|
|
970
|
+
**Supported skills**:
|
|
971
|
+
|
|
972
|
+
- **Smart home**: device control, scene management
|
|
973
|
+
- **Knowledge base search**: display of related documents
|
|
974
|
+
|
|
975
|
+
#### Configuration Options
|
|
976
|
+
|
|
977
|
+
```tsx
|
|
978
|
+
withBuildIn({
|
|
979
|
+
// Whether to enable TTS auto-play by default, defaults to false
|
|
980
|
+
audioAutoPlay: true,
|
|
981
|
+
});
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
#### TTS Audio Playback
|
|
985
|
+
|
|
986
|
+
When `withAIStream({ enableTts: true })` is enabled, the server sends TTS audio packets along with messages. `withBuildIn` consumes these audio packets and provides full playback capabilities:
|
|
987
|
+
|
|
988
|
+
- **Auto-play**: when the audio stream starts (`StreamFlag.START`), if `AIStream.audioAutoPlay` is `true`, playback starts automatically.
|
|
989
|
+
- **Bubble play button**: after the audio stream ends, a `bubbleTool` tile (audio play / copy button) is inserted into the corresponding bubble. The playback parameters (`path` / `codecType` / `sampleRate` / `channels` / `bitDepth` / `pts`) are aggregated by audio stream id and written to the tile, so clicking replays the audio.
|
|
990
|
+
- **Single-item exclusivity**: only one item plays at a time. Starting a new playback or actively stopping will first stop the current playback.
|
|
991
|
+
- **Playback lifecycle**: it listens to the underlying `onAudioPlayChanged` and automatically resets the playback state when playback completes or errors.
|
|
992
|
+
|
|
993
|
+
**Exposed session state** (all broadcast via the `sessionChange` event; on the UI side you can subscribe with `useAgentSessionValue` and derive component state):
|
|
994
|
+
|
|
995
|
+
| key | Type | Description |
|
|
996
|
+
| --------------------------- | ---------------- | ------------------------------------ |
|
|
997
|
+
| `AIStream.audioAutoPlay` | `boolean` | Whether TTS auto-play is enabled |
|
|
998
|
+
| `AIStream.audioPlaying` | `boolean` | Whether playback is currently active |
|
|
999
|
+
| `AIStream.playingMessageId` | `string \| null` | The id of the message being played |
|
|
1000
|
+
|
|
1001
|
+
**Exposed UI events**:
|
|
1002
|
+
|
|
1003
|
+
| Event | Description |
|
|
1004
|
+
| --------------- | ------------------------------------------------------------------- |
|
|
1005
|
+
| `audioPlayStop` | Actively stop the current playback (whether or not auto-play is on) |
|
|
859
1006
|
|
|
860
|
-
|
|
1007
|
+
Example: a three-state (playing / auto-play / muted) toggle button at the top of the page:
|
|
861
1008
|
|
|
862
|
-
|
|
1009
|
+
```tsx
|
|
1010
|
+
import { useAgentSessionValue, useEmitEvent } from '@ray-js/t-agent-ui-ray';
|
|
1011
|
+
|
|
1012
|
+
function AudioToggle() {
|
|
1013
|
+
const [audioAutoPlay, setAudioAutoPlay] = useAgentSessionValue<boolean>('AIStream.audioAutoPlay');
|
|
1014
|
+
const [audioPlaying] = useAgentSessionValue<boolean>('AIStream.audioPlaying');
|
|
1015
|
+
const emitEvent = useEmitEvent();
|
|
1016
|
+
|
|
1017
|
+
const onClick = () => {
|
|
1018
|
+
if (audioPlaying) {
|
|
1019
|
+
// Playing: clicking immediately stops playback, regardless of mute state
|
|
1020
|
+
emitEvent('audioPlayStop', undefined);
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
// Otherwise toggle auto-play / mute
|
|
1024
|
+
setAudioAutoPlay(prev => !prev);
|
|
1025
|
+
};
|
|
863
1026
|
|
|
864
|
-
|
|
865
|
-
|
|
1027
|
+
const label = audioPlaying ? '🎵 Playing' : audioAutoPlay ? '🔊 Auto-play' : '🔇 Muted';
|
|
1028
|
+
return <View onClick={onClick}>{label}</View>;
|
|
1029
|
+
}
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
> The `playing` state inside a component should be derived from the session (e.g. `audioPlaying && playingMessageId === message.id`). Do not maintain local playback state inside a tile, to avoid it being persisted or becoming inconsistent with the global state.
|
|
866
1033
|
|
|
867
1034
|
## Mock Mechanism
|
|
868
1035
|
|
|
869
|
-
To
|
|
1036
|
+
To make development easier, we provide a mock mechanism that lets you develop without connecting to the mini-program AI agent platform — you can develop directly using mock data.
|
|
870
1037
|
|
|
871
1038
|
### Mock AI Stream Response
|
|
872
1039
|
|
|
@@ -879,7 +1046,7 @@ mock.hooks.hook('sendToAIStream', context => {
|
|
|
879
1046
|
}
|
|
880
1047
|
|
|
881
1048
|
if (context.options.blocks?.some(block => block.text?.includes('smart home'))) {
|
|
882
|
-
context.responseText = 'Controlling smart devices
|
|
1049
|
+
context.responseText = 'Controlling your smart devices...';
|
|
883
1050
|
context.responseSkills = [
|
|
884
1051
|
{
|
|
885
1052
|
code: 'smart_home',
|
|
@@ -891,7 +1058,7 @@ mock.hooks.hook('sendToAIStream', context => {
|
|
|
891
1058
|
deviceId: 'vdevo174796589841019',
|
|
892
1059
|
icon: '',
|
|
893
1060
|
dps: { range: '0', toggle: 'ON' },
|
|
894
|
-
name: 'Towel
|
|
1061
|
+
name: 'Towel rack',
|
|
895
1062
|
},
|
|
896
1063
|
],
|
|
897
1064
|
},
|
|
@@ -903,7 +1070,7 @@ mock.hooks.hook('sendToAIStream', context => {
|
|
|
903
1070
|
});
|
|
904
1071
|
```
|
|
905
1072
|
|
|
906
|
-
###
|
|
1073
|
+
### Mock ASR Speech Recognition
|
|
907
1074
|
|
|
908
1075
|
```tsx
|
|
909
1076
|
import { mock } from '@ray-js/t-agent-plugin-aistream';
|
|
@@ -913,25 +1080,111 @@ mock.hooks.hook('asrDetection', context => {
|
|
|
913
1080
|
});
|
|
914
1081
|
```
|
|
915
1082
|
|
|
916
|
-
|
|
1083
|
+
### Mock MCP
|
|
1084
|
+
|
|
1085
|
+
The recommended approach is to decide which MCP tool to call inside the mock `sendToAIStream` hook based on the input content, and then run the full MCP call chain directly via `context.callMCPTool()`.
|
|
1086
|
+
|
|
1087
|
+
```tsx
|
|
1088
|
+
import { mock } from '@ray-js/t-agent-plugin-aistream';
|
|
1089
|
+
|
|
1090
|
+
const getToolCall = (text: string) => {
|
|
1091
|
+
if (text.includes('error') || text.includes('fail') || text.includes('exception')) {
|
|
1092
|
+
return {
|
|
1093
|
+
name: 'device.home.energy.summary.fail',
|
|
1094
|
+
arguments: {
|
|
1095
|
+
reason: 'mock-error-case',
|
|
1096
|
+
},
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
if (text.includes('energy') || text.includes('power') || text.includes('data')) {
|
|
1101
|
+
return {
|
|
1102
|
+
name: 'device.home.energy.summary.get',
|
|
1103
|
+
arguments: {
|
|
1104
|
+
period: 'today',
|
|
1105
|
+
},
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
return {
|
|
1110
|
+
name: 'device.app.open',
|
|
1111
|
+
arguments: {
|
|
1112
|
+
category: 'music',
|
|
1113
|
+
},
|
|
1114
|
+
};
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
export const setupMockMCP = () => {
|
|
1118
|
+
mock.hooks.hook('sendToAIStream', async context => {
|
|
1119
|
+
const text = context.data
|
|
1120
|
+
.filter(item => item.type === 'text')
|
|
1121
|
+
.map(item => item.text)
|
|
1122
|
+
.join(' ');
|
|
1123
|
+
|
|
1124
|
+
if (!/mcp|app|energy|power|data|error|fail|exception/i.test(text)) {
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
const toolCall = getToolCall(text);
|
|
1129
|
+
|
|
1130
|
+
await context.writeText(`MCP mock is calling ${toolCall.name}...`);
|
|
1131
|
+
|
|
1132
|
+
try {
|
|
1133
|
+
const result = await context.callMCPTool(toolCall.name, toolCall.arguments, {
|
|
1134
|
+
delayMs: 80,
|
|
1135
|
+
});
|
|
1136
|
+
await context.writeText(
|
|
1137
|
+
`Tool ${toolCall.name} returned: ${
|
|
1138
|
+
typeof result === 'string' ? result : JSON.stringify(result == null ? {} : result)
|
|
1139
|
+
}`
|
|
1140
|
+
);
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1143
|
+
await context.writeText(`MCP mock received a tool error: ${message}`);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
await context.end();
|
|
1147
|
+
});
|
|
1148
|
+
};
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
Just register it once before creating the agent:
|
|
1152
|
+
|
|
1153
|
+
```tsx
|
|
1154
|
+
const createAgent = () => {
|
|
1155
|
+
setupMockMCP();
|
|
1156
|
+
|
|
1157
|
+
return createChatAgent(
|
|
1158
|
+
withUI(),
|
|
1159
|
+
withAIStream({
|
|
1160
|
+
agentId: 'your-agent-id',
|
|
1161
|
+
}),
|
|
1162
|
+
withMCP({
|
|
1163
|
+
createServer: () => server,
|
|
1164
|
+
})
|
|
1165
|
+
);
|
|
1166
|
+
};
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
## Bundled utils (currently unstable, still under development)
|
|
917
1170
|
|
|
918
1171
|
### AbortController
|
|
919
1172
|
|
|
920
|
-
This is
|
|
1173
|
+
This is a ponyfill of AbortController for the mini-program; see MDN.
|
|
921
1174
|
|
|
922
1175
|
### runTTTAction
|
|
923
1176
|
|
|
924
|
-
Run a TTTAction to handle user
|
|
1177
|
+
Run a TTTAction to handle the user's operation behavior. The following actions are currently supported:
|
|
925
1178
|
|
|
926
|
-
- `openRoute`
|
|
927
|
-
- `openMiniApp`
|
|
928
|
-
- `openH5`
|
|
929
|
-
- `sendMessage`
|
|
930
|
-
- `buildIn`
|
|
1179
|
+
- `openRoute` — open a route
|
|
1180
|
+
- `openMiniApp` — open a mini-program
|
|
1181
|
+
- `openH5` — open an H5 page
|
|
1182
|
+
- `sendMessage` — send a message
|
|
1183
|
+
- `buildIn` — built-in action
|
|
931
1184
|
|
|
932
1185
|
### AsrAgent
|
|
933
1186
|
|
|
934
|
-
ASR Speech Recognition agent
|
|
1187
|
+
An ASR (Automatic Speech Recognition) agent used to recognize the user's voice input.
|
|
935
1188
|
|
|
936
1189
|
Usage:
|
|
937
1190
|
|
|
@@ -949,7 +1202,7 @@ async function startAsr() {
|
|
|
949
1202
|
}
|
|
950
1203
|
},
|
|
951
1204
|
onFinish: () => {
|
|
952
|
-
console.log('Recognition
|
|
1205
|
+
console.log('Recognition finished');
|
|
953
1206
|
},
|
|
954
1207
|
onError: error => {
|
|
955
1208
|
console.error('Recognition error:', error);
|
|
@@ -957,7 +1210,7 @@ async function startAsr() {
|
|
|
957
1210
|
recordingOptions: {
|
|
958
1211
|
saveFile: false,
|
|
959
1212
|
sampleRate: 16000,
|
|
960
|
-
maxDuration: 60000, //
|
|
1213
|
+
maxDuration: 60000, // Up to 60 seconds
|
|
961
1214
|
},
|
|
962
1215
|
});
|
|
963
1216
|
|
|
@@ -971,7 +1224,7 @@ async function startAsr() {
|
|
|
971
1224
|
|
|
972
1225
|
### promisify TTT
|
|
973
1226
|
|
|
974
|
-
|
|
1227
|
+
Provides built-in promisify methods for a large number of TTT APIs, used to convert TTT APIs into Promises, with mock support.
|
|
975
1228
|
|
|
976
1229
|
Usage:
|
|
977
1230
|
|
|
@@ -979,7 +1232,7 @@ Usage:
|
|
|
979
1232
|
import { promisify } from '@ray-js/t-agent-plugin-aistream';
|
|
980
1233
|
|
|
981
1234
|
interface RouterParams {
|
|
982
|
-
/**
|
|
1235
|
+
/** The route URL */
|
|
983
1236
|
url: string;
|
|
984
1237
|
complete?: () => void;
|
|
985
1238
|
success?: (params: null) => void;
|
|
@@ -994,27 +1247,27 @@ interface RouterParams {
|
|
|
994
1247
|
}
|
|
995
1248
|
const router = promisify<RouterParams>(ty.router);
|
|
996
1249
|
|
|
997
|
-
// mock, only
|
|
1250
|
+
// mock, only takes effect in the IDE
|
|
998
1251
|
mock.hooks.hook('router', context => {
|
|
999
1252
|
console.log('call router', context.options);
|
|
1000
1253
|
});
|
|
1001
1254
|
|
|
1002
|
-
//
|
|
1255
|
+
// Call
|
|
1003
1256
|
await router({ url: '/pages/index/index' });
|
|
1004
1257
|
```
|
|
1005
1258
|
|
|
1006
1259
|
### sendBlocksToAIStream
|
|
1007
1260
|
|
|
1008
|
-
**Note:
|
|
1261
|
+
**Note: this function is for internal use only; regular developers generally do not need to call it directly.**
|
|
1009
1262
|
|
|
1010
|
-
Send message blocks to AIStream. This is a low-level function
|
|
1263
|
+
Send message blocks to AIStream. This is a low-level function — you should generally use the `agent.plugins.aiStream.send` or `agent.plugins.aiStream.chat` methods.
|
|
1011
1264
|
|
|
1012
|
-
#### Use
|
|
1265
|
+
#### When to Use
|
|
1013
1266
|
|
|
1014
|
-
- ✅ **Suitable**:
|
|
1015
|
-
- ✅ **Suitable**:
|
|
1016
|
-
- ❌ **Not suitable**:
|
|
1017
|
-
- ❌ **Not suitable**:
|
|
1267
|
+
- ✅ **Suitable**: when you need direct control over how the streaming response is handled
|
|
1268
|
+
- ✅ **Suitable**: when implementing custom message-sending logic
|
|
1269
|
+
- ❌ **Not suitable**: for regular conversation scenarios — use `agent.plugins.aiStream.chat`
|
|
1270
|
+
- ❌ **Not suitable**: for simple message sending — use `agent.plugins.aiStream.send`
|
|
1018
1271
|
|
|
1019
1272
|
#### Function Signature
|
|
1020
1273
|
|
|
@@ -1039,7 +1292,7 @@ export function sendBlocksToAIStream(params: SendBlocksToAIStreamParams): {
|
|
|
1039
1292
|
```tsx
|
|
1040
1293
|
const send = async () => {
|
|
1041
1294
|
try {
|
|
1042
|
-
//
|
|
1295
|
+
// You need to get the AIStreamSession object first
|
|
1043
1296
|
const streamSession = agent.session.get('AIStream.streamSession');
|
|
1044
1297
|
|
|
1045
1298
|
const result = sendBlocksToAIStream({
|
|
@@ -1048,10 +1301,10 @@ const send = async () => {
|
|
|
1048
1301
|
signal: new AbortController().signal,
|
|
1049
1302
|
});
|
|
1050
1303
|
|
|
1051
|
-
// Get metadata after sending
|
|
1304
|
+
// Get the metadata after sending
|
|
1052
1305
|
const meta = await result.metaPromise;
|
|
1053
1306
|
|
|
1054
|
-
// Get
|
|
1307
|
+
// Get the streaming messages
|
|
1055
1308
|
const parts = result.response.parts();
|
|
1056
1309
|
for await (const part of parts) {
|
|
1057
1310
|
console.log('part', part);
|
|
@@ -1063,66 +1316,31 @@ const send = async () => {
|
|
|
1063
1316
|
};
|
|
1064
1317
|
```
|
|
1065
1318
|
|
|
1066
|
-
###
|
|
1319
|
+
### Media File Functions
|
|
1067
1320
|
|
|
1068
|
-
|
|
1321
|
+
`uploadMedia`, `uploadVideo`, `uploadImage` — upload media files, with caching.
|
|
1069
1322
|
|
|
1070
|
-
|
|
1323
|
+
`isFullLink` — determine whether a link starts with the http(s) protocol.
|
|
1071
1324
|
|
|
1072
|
-
|
|
1073
|
-
import { authorizeAIStreamPolicy } from '@ray-js/t-agent-plugin-aistream';
|
|
1325
|
+
`parseCloudKey` — parse the cloud storage key from a URL.
|
|
1074
1326
|
|
|
1075
|
-
|
|
1076
|
-
const authorize = async () => {
|
|
1077
|
-
try {
|
|
1078
|
-
const result = await authorizeAIStreamPolicy();
|
|
1079
|
-
|
|
1080
|
-
if (result) {
|
|
1081
|
-
// Already agreed or clicked the agree button
|
|
1082
|
-
console.log('User agreed to the AI privacy policy');
|
|
1083
|
-
} else {
|
|
1084
|
-
ty.exitMiniProgram({});
|
|
1085
|
-
console.log('User declined the AI privacy policy');
|
|
1086
|
-
}
|
|
1087
|
-
} catch (e) {
|
|
1088
|
-
// Popup error message
|
|
1089
|
-
ty.showToast({
|
|
1090
|
-
title: I18n.t('get_sign_error'),
|
|
1091
|
-
icon: 'error',
|
|
1092
|
-
});
|
|
1093
|
-
// Delay to allow the user to read clearly
|
|
1094
|
-
setTimeout(() => {
|
|
1095
|
-
ty.exitMiniProgram({});
|
|
1096
|
-
}, 1000);
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
```
|
|
1327
|
+
`isLinkExpired` — determine whether a link has expired.
|
|
1100
1328
|
|
|
1101
|
-
|
|
1329
|
+
`getUrlByCloudKey` — get the cloud storage download signed URL from the cache; returns `undefined` if not present.
|
|
1102
1330
|
|
|
1103
|
-
`
|
|
1331
|
+
`setUrlByCloudKey` — set the cloud storage download signed URL into the cache.
|
|
1104
1332
|
|
|
1105
|
-
`
|
|
1333
|
+
`resetUrlByCloudKey` — reset the cloud storage download signed URL cache.
|
|
1106
1334
|
|
|
1107
|
-
`
|
|
1108
|
-
|
|
1109
|
-
`isLinkExpired` is used to determine whether the link is expired
|
|
1110
|
-
|
|
1111
|
-
`getUrlByCloudKey` is used to get the signed download URL of cloud storage from the cache, otherwise returns `undefined`
|
|
1112
|
-
|
|
1113
|
-
`setUrlByCloudKey` is used to set the signed download URL of cloud storage into the cache
|
|
1114
|
-
|
|
1115
|
-
`resetUrlByCloudKey` is used to reset the cache of the signed download URL of cloud storage
|
|
1116
|
-
|
|
1117
|
-
`chooseImage`, `chooseVideo` are used to select media files
|
|
1335
|
+
`chooseImage`, `chooseVideo` — choose media files.
|
|
1118
1336
|
|
|
1119
1337
|
```tsx
|
|
1120
1338
|
import { useEffect } from 'react';
|
|
1121
1339
|
|
|
1122
1340
|
async function getPictureList() {
|
|
1123
|
-
//
|
|
1341
|
+
// Fetch the user's private picture list from the cloud
|
|
1124
1342
|
const list = await pictureListRequest();
|
|
1125
|
-
// Set into the cache
|
|
1343
|
+
// Set them into the cache so that no request is needed next time
|
|
1126
1344
|
for (const item of list) {
|
|
1127
1345
|
setUrlByCloudKey(item.path, item.displayUrl);
|
|
1128
1346
|
}
|
|
@@ -1131,7 +1349,7 @@ async function getPictureList() {
|
|
|
1131
1349
|
|
|
1132
1350
|
# t-agent-ui-ray
|
|
1133
1351
|
|
|
1134
|
-
t-agent-ui-ray is a UI component library
|
|
1352
|
+
t-agent-ui-ray is a Ray-based UI component library that contains common chat UI components, such as the message list and the message input field.
|
|
1135
1353
|
|
|
1136
1354
|
## Installation
|
|
1137
1355
|
|
|
@@ -1142,17 +1360,30 @@ yarn add @ray-js/t-agent-ui-ray
|
|
|
1142
1360
|
## Usage
|
|
1143
1361
|
|
|
1144
1362
|
```tsx
|
|
1145
|
-
import
|
|
1146
|
-
|
|
1363
|
+
import React from 'react';
|
|
1364
|
+
import { View } from '@ray-js/components';
|
|
1365
|
+
import {
|
|
1366
|
+
ChatContainer,
|
|
1367
|
+
defaultRenderOptions,
|
|
1368
|
+
MessageActionBar,
|
|
1369
|
+
MessageInput,
|
|
1370
|
+
MessageList,
|
|
1371
|
+
} from '@ray-js/t-agent-ui-ray';
|
|
1372
|
+
// See the t-agent usage example for the createAgent implementation
|
|
1147
1373
|
import { createAgent } from './createAgent';
|
|
1148
1374
|
|
|
1375
|
+
const renderOptions = {
|
|
1376
|
+
...defaultRenderOptions,
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1149
1379
|
export default function ChatPage() {
|
|
1150
|
-
// createAgent must return a ChatAgent instance
|
|
1380
|
+
// createAgent must return a ChatAgent instance with the withUI and withAIStream plugins applied
|
|
1151
1381
|
return (
|
|
1152
1382
|
<View style={{ height: '100vh' }}>
|
|
1153
|
-
<ChatContainer createAgent={createAgent}>
|
|
1383
|
+
<ChatContainer createAgent={createAgent} renderOptions={renderOptions}>
|
|
1154
1384
|
<MessageList />
|
|
1155
1385
|
<MessageInput />
|
|
1386
|
+
<MessageActionBar />
|
|
1156
1387
|
</ChatContainer>
|
|
1157
1388
|
</View>
|
|
1158
1389
|
);
|
|
@@ -1163,75 +1394,84 @@ export default function ChatPage() {
|
|
|
1163
1394
|
|
|
1164
1395
|
### ChatContainer
|
|
1165
1396
|
|
|
1166
|
-
|
|
1397
|
+
The chat container, used to wrap the message list and the message input field. It provides the `ChatAgent` context.
|
|
1167
1398
|
|
|
1168
|
-
|
|
1399
|
+
Props:
|
|
1169
1400
|
|
|
1170
|
-
- `className`
|
|
1171
|
-
- `createAgent`
|
|
1172
|
-
- `agentRef`
|
|
1173
|
-
- `renderOptions`
|
|
1174
|
-
- `renderTileAs`
|
|
1175
|
-
- `customBlockTypes`
|
|
1176
|
-
- `renderCustomBlockAs`
|
|
1177
|
-
- `renderCardAs`
|
|
1178
|
-
- `renderLongPressAs` **(0.2.x
|
|
1179
|
-
- `formatErrorMessageAs` **(0.2.x
|
|
1180
|
-
- `customCardMap`
|
|
1181
|
-
- `getStaticResourceBizType`
|
|
1401
|
+
- `className` — the container's class name
|
|
1402
|
+
- `createAgent` — a function that creates the `ChatAgent`; it is called to create the `ChatAgent` instance after `ChatContainer` mounts
|
|
1403
|
+
- `agentRef` — a ref used to obtain the `ChatAgent` instance
|
|
1404
|
+
- `renderOptions` — render options that determine how each element in the `MessageList` is rendered; see the "renderOptions custom rendering" section below
|
|
1405
|
+
- `renderTileAs` — a function that determines how to render a tile within a message
|
|
1406
|
+
- `customBlockTypes` — custom block types; only block types registered here will be rendered by `renderCustomBlockAs`
|
|
1407
|
+
- `renderCustomBlockAs` — a function that determines how to render a custom block in a markdown bubble message; `echarts` is supported by default
|
|
1408
|
+
- `renderCardAs` — a function that determines how to render a card within a message; you generally do not need to customize this
|
|
1409
|
+
- `renderLongPressAs` **(new in 0.2.x)** — a function that determines how to render the long-press menu; you can customize the long-press menu's style and behavior
|
|
1410
|
+
- `formatErrorMessageAs` **(new in 0.2.x)** — a function that determines how to format error messages; you can return a user-friendly message based on the error code
|
|
1411
|
+
- `customCardMap` — a custom card map; without modifying `renderCardAs`, you just register card types and their corresponding components here
|
|
1412
|
+
- `getStaticResourceBizType` — get the static resource `bizType`, used to fetch static resources
|
|
1182
1413
|
|
|
1183
1414
|
### MessageList
|
|
1184
1415
|
|
|
1185
|
-
|
|
1416
|
+
The message list, used to display messages. In 0.2.x, it integrates the LazyScrollView component for better performance.
|
|
1186
1417
|
|
|
1187
1418
|
**Props**:
|
|
1188
1419
|
|
|
1189
|
-
- `className`
|
|
1190
|
-
- `roleSide`
|
|
1420
|
+
- `className` — the list's class name
|
|
1421
|
+
- `roleSide` — the alignment of message roles, defaults to `{ user: 'end', assistant: 'start' }`
|
|
1191
1422
|
|
|
1192
|
-
**LazyScrollView
|
|
1423
|
+
**LazyScrollView integration (new in 0.2.x)**:
|
|
1193
1424
|
|
|
1194
|
-
MessageList internally uses LazyScrollView component to optimize performance
|
|
1425
|
+
MessageList internally uses the LazyScrollView component to optimize rendering performance for large numbers of messages:
|
|
1195
1426
|
|
|
1196
|
-
- **Lazy
|
|
1197
|
-
- **
|
|
1198
|
-
- **notifyHeightChanged()**:
|
|
1427
|
+
- **Lazy rendering**: only renders messages within the visible area, greatly improving performance
|
|
1428
|
+
- **Adaptive height**: automatically calculates message heights, supporting dynamic content
|
|
1429
|
+
- **notifyHeightChanged()**: automatically notifies a height update when message content changes
|
|
1199
1430
|
|
|
1200
1431
|
The component automatically handles the following scenarios:
|
|
1201
1432
|
|
|
1202
|
-
-
|
|
1203
|
-
- Automatically updates scroll position when message heights change
|
|
1204
|
-
- Supports
|
|
1433
|
+
- Always renders the bottom 10 messages, avoiding a blank screen when scrolling to the bottom
|
|
1434
|
+
- Automatically updates the scroll position when message heights change
|
|
1435
|
+
- Supports the scroll-to-bottom animation effect
|
|
1205
1436
|
|
|
1206
1437
|
### MessageInput
|
|
1207
1438
|
|
|
1208
|
-
|
|
1439
|
+
The message input field, used for typing messages, uploading attachments, and ASR speech recognition.
|
|
1440
|
+
|
|
1441
|
+
Props:
|
|
1209
1442
|
|
|
1210
|
-
|
|
1443
|
+
- `className` — the input field's class name
|
|
1444
|
+
- `placeholder` — the input field's placeholder
|
|
1445
|
+
- `placeholderStyle` — the placeholder's style
|
|
1446
|
+
- `renderTop` — used to render content above the input field
|
|
1447
|
+
- `style` — the input container's style
|
|
1448
|
+
- `attachment` — whether to enable attachment upload, or pass `{ image, video, imageCount, videoCount }` for fine-grained control
|
|
1449
|
+
- `maxTextLength` — the maximum text length, defaults to 200
|
|
1450
|
+
- `maxAudioMs` — the maximum recording duration
|
|
1451
|
+
- `onStateChange` — callback for input field state changes; see `MessageInputState` for state values
|
|
1452
|
+
- `amplitudeCount` — the number of amplitude samples for the voice waveform
|
|
1211
1453
|
|
|
1212
|
-
|
|
1213
|
-
- `placeholder` Placeholder of the input box
|
|
1214
|
-
- `renderTop` Used to render content above the input box
|
|
1454
|
+
`MessageInput` currently exports `MessageInputAIStream` by default, suitable for scenarios where `withAIStream` has already been integrated.
|
|
1215
1455
|
|
|
1216
|
-
### MessageActionBar (0.2.x
|
|
1456
|
+
### MessageActionBar (new in 0.2.x)
|
|
1217
1457
|
|
|
1218
|
-
|
|
1458
|
+
The message action bar component, used to show action buttons when multi-selecting messages. It supports deleting selected messages and clearing history.
|
|
1219
1459
|
|
|
1220
1460
|
**Props**:
|
|
1221
1461
|
|
|
1222
|
-
No props need to be passed
|
|
1462
|
+
No props need to be passed; the component automatically shows and hides based on the multi-select state.
|
|
1223
1463
|
|
|
1224
1464
|
**Features**:
|
|
1225
1465
|
|
|
1226
|
-
- **Back
|
|
1227
|
-
- **Clear
|
|
1228
|
-
- **Delete
|
|
1466
|
+
- **Back button**: exit multi-select mode
|
|
1467
|
+
- **Clear history button**: clear all history messages; calls the `onClearHistory` hook
|
|
1468
|
+
- **Delete selected button**: delete the currently selected messages; the button is disabled when no messages are selected
|
|
1229
1469
|
|
|
1230
|
-
**How it
|
|
1470
|
+
**How it works**:
|
|
1231
1471
|
|
|
1232
|
-
MessageActionBar component
|
|
1472
|
+
The MessageActionBar component listens to the `UIRay.multiSelect.show` state in the session data to decide whether to show. When the user long-presses a message and selects "Multi-select", the component automatically appears.
|
|
1233
1473
|
|
|
1234
|
-
**Usage
|
|
1474
|
+
**Usage example**:
|
|
1235
1475
|
|
|
1236
1476
|
```tsx
|
|
1237
1477
|
export default function ChatPage() {
|
|
@@ -1249,31 +1489,31 @@ export default function ChatPage() {
|
|
|
1249
1489
|
|
|
1250
1490
|
### PrivateImage
|
|
1251
1491
|
|
|
1252
|
-
|
|
1492
|
+
The private image component, used to display private images. Its props are the same as `Image`, with an added `bizType` parameter.
|
|
1253
1493
|
|
|
1254
1494
|
### LazyScrollView
|
|
1255
1495
|
|
|
1256
|
-
|
|
1496
|
+
The lazy-loading scroll view component, used to optimize long list performance by automatically managing the rendering of the visible area.
|
|
1257
1497
|
|
|
1258
|
-
Main
|
|
1498
|
+
Main features:
|
|
1259
1499
|
|
|
1260
|
-
- Virtual
|
|
1261
|
-
- Height
|
|
1262
|
-
- Dynamic
|
|
1263
|
-
- `notifyHeightChanged()
|
|
1500
|
+
- Virtual scrolling: only renders elements in the visible area
|
|
1501
|
+
- Height caching: automatically caches element heights to improve scrolling performance
|
|
1502
|
+
- Dynamic loading: dynamically shows/hides elements based on the scroll position
|
|
1503
|
+
- `notifyHeightChanged()`: when an element's height changes, you can call this method to notify the scroll view to update
|
|
1264
1504
|
|
|
1265
|
-
Usage
|
|
1505
|
+
Usage notes:
|
|
1266
1506
|
|
|
1267
|
-
LazyScrollView is mainly used internally by MessageList
|
|
1507
|
+
LazyScrollView is mainly used internally by MessageList; developers generally do not need to use it directly. If you need to dynamically change the height within a message, you can use the `notifyHeightChanged` parameter to notify of the height change:
|
|
1268
1508
|
|
|
1269
1509
|
```tsx
|
|
1270
|
-
//
|
|
1510
|
+
// Used inside a tile component
|
|
1271
1511
|
const MyTile = ({ notifyHeightChanged }) => {
|
|
1272
1512
|
const [expanded, setExpanded] = useState(false);
|
|
1273
1513
|
|
|
1274
1514
|
const handleToggle = () => {
|
|
1275
1515
|
setExpanded(!expanded);
|
|
1276
|
-
// Notify height change
|
|
1516
|
+
// Notify of the height change
|
|
1277
1517
|
notifyHeightChanged();
|
|
1278
1518
|
};
|
|
1279
1519
|
|
|
@@ -1288,38 +1528,39 @@ const MyTile = ({ notifyHeightChanged }) => {
|
|
|
1288
1528
|
|
|
1289
1529
|
### Built-in tile components
|
|
1290
1530
|
|
|
1291
|
-
- bubble
|
|
1292
|
-
- buttons
|
|
1293
|
-
- card
|
|
1294
|
-
-
|
|
1295
|
-
-
|
|
1296
|
-
-
|
|
1297
|
-
-
|
|
1298
|
-
-
|
|
1299
|
-
-
|
|
1300
|
-
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
-
|
|
1531
|
+
- bubble — bubble
|
|
1532
|
+
- buttons — button group
|
|
1533
|
+
- card — card
|
|
1534
|
+
- divider — divider
|
|
1535
|
+
- documents — related documents
|
|
1536
|
+
- executeCard — execution result card
|
|
1537
|
+
- file — file
|
|
1538
|
+
- image — image
|
|
1539
|
+
- operateCard — operation result card
|
|
1540
|
+
- recommendations — recommended actions
|
|
1541
|
+
- text — text, with markdown support
|
|
1542
|
+
- time — time label
|
|
1543
|
+
- tip — tip
|
|
1544
|
+
- video — video
|
|
1545
|
+
- workflow — workflow options
|
|
1305
1546
|
|
|
1306
1547
|
## React Hooks
|
|
1307
1548
|
|
|
1308
1549
|
### useChatAgent
|
|
1309
1550
|
|
|
1310
|
-
Get `ChatAgent` instance
|
|
1551
|
+
Get the `ChatAgent` instance within the `ChatContainer` context.
|
|
1311
1552
|
|
|
1312
1553
|
### useAgentMessage
|
|
1313
1554
|
|
|
1314
|
-
Get `messages: ChatMessageObject[]` list
|
|
1555
|
+
Get the `messages: ChatMessageObject[]` list within the `ChatContainer` context.
|
|
1315
1556
|
|
|
1316
1557
|
### useRenderOptions
|
|
1317
1558
|
|
|
1318
|
-
Get `renderOptions` object
|
|
1559
|
+
Get the `renderOptions` object within the `ChatContainer` context.
|
|
1319
1560
|
|
|
1320
1561
|
### useOnEvent
|
|
1321
1562
|
|
|
1322
|
-
Register UI
|
|
1563
|
+
Register a UI event within the `ChatContainer` context; it is automatically unregistered when the component unmounts.
|
|
1323
1564
|
|
|
1324
1565
|
```tsx
|
|
1325
1566
|
import { useOnEvent } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1335,7 +1576,7 @@ const MyComponent = () => {
|
|
|
1335
1576
|
|
|
1336
1577
|
### useEmitEvent
|
|
1337
1578
|
|
|
1338
|
-
|
|
1579
|
+
Emit a UI event within the `ChatContainer` context.
|
|
1339
1580
|
|
|
1340
1581
|
```tsx
|
|
1341
1582
|
import { useEmitEvent } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1353,7 +1594,7 @@ const MyComponent = () => {
|
|
|
1353
1594
|
|
|
1354
1595
|
### useTileProps
|
|
1355
1596
|
|
|
1356
|
-
Get the `TileProps` object
|
|
1597
|
+
Get the `TileProps` object within a tile component. If you're in a tile, you can get it directly from props.
|
|
1357
1598
|
|
|
1358
1599
|
```tsx
|
|
1359
1600
|
import { useTileProps } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1367,16 +1608,23 @@ const MyTilePart = () => {
|
|
|
1367
1608
|
|
|
1368
1609
|
### useSendAction
|
|
1369
1610
|
|
|
1370
|
-
Send a TTTAction
|
|
1611
|
+
Send a TTTAction.
|
|
1612
|
+
|
|
1613
|
+
If the current component is inside a tile or card, it goes through `emitTileEvent` first.
|
|
1614
|
+
If the current component is just a regular child component under `ChatContainer`, it falls back to triggering the `runTTTAction` UI event.
|
|
1371
1615
|
|
|
1372
1616
|
```tsx
|
|
1373
1617
|
import { useSendAction } from '@ray-js/t-agent-ui-ray';
|
|
1374
1618
|
|
|
1375
|
-
const
|
|
1619
|
+
const ActionPanel = () => {
|
|
1376
1620
|
const sendAction = useSendAction();
|
|
1377
1621
|
|
|
1378
1622
|
const handleClick = () => {
|
|
1379
|
-
sendAction({
|
|
1623
|
+
sendAction({
|
|
1624
|
+
type: 'sendMessage',
|
|
1625
|
+
blocks: [{ type: 'text', text: 'hello' }],
|
|
1626
|
+
sendImmediately: true,
|
|
1627
|
+
});
|
|
1380
1628
|
};
|
|
1381
1629
|
|
|
1382
1630
|
return <button onClick={handleClick}>Send Message</button>;
|
|
@@ -1385,7 +1633,7 @@ const MyTilePart = () => {
|
|
|
1385
1633
|
|
|
1386
1634
|
### useTranslate
|
|
1387
1635
|
|
|
1388
|
-
Get internationalization translation function
|
|
1636
|
+
Get the internationalization translation function, used to translate UI text, with full multilingual support.
|
|
1389
1637
|
|
|
1390
1638
|
```tsx
|
|
1391
1639
|
import { useTranslate } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1403,24 +1651,24 @@ const MyComponent = () => {
|
|
|
1403
1651
|
};
|
|
1404
1652
|
```
|
|
1405
1653
|
|
|
1406
|
-
**Supported
|
|
1654
|
+
**Supported languages**:
|
|
1407
1655
|
|
|
1408
|
-
|
|
1656
|
+
The built-in multilingual support includes:
|
|
1409
1657
|
|
|
1410
|
-
- **Simplified Chinese** (`zh-Hans`)
|
|
1411
|
-
- **Traditional Chinese** (`zh-Hant`)
|
|
1412
|
-
- **English** (`en`)
|
|
1413
|
-
- **Japanese** (`ja`)
|
|
1414
|
-
- **German** (`de`)
|
|
1415
|
-
- **French** (`fr`)
|
|
1416
|
-
- **Spanish** (`es`)
|
|
1417
|
-
- **Italian** (`it`)
|
|
1658
|
+
- **Simplified Chinese** (`zh-Hans`)
|
|
1659
|
+
- **Traditional Chinese** (`zh-Hant`)
|
|
1660
|
+
- **English** (`en`)
|
|
1661
|
+
- **Japanese** (`ja`)
|
|
1662
|
+
- **German** (`de`)
|
|
1663
|
+
- **French** (`fr`)
|
|
1664
|
+
- **Spanish** (`es`)
|
|
1665
|
+
- **Italian** (`it`)
|
|
1418
1666
|
|
|
1419
1667
|
The system automatically selects the corresponding translation based on the user's system language, falling back to English if the current language is not supported.
|
|
1420
1668
|
|
|
1421
1669
|
## renderOptions Custom Rendering
|
|
1422
1670
|
|
|
1423
|
-
###
|
|
1671
|
+
### Replacing or Adding a Tile
|
|
1424
1672
|
|
|
1425
1673
|
If you need to replace a tile with your own implementation, or add a new tile, you can override `renderTileAs`, for example:
|
|
1426
1674
|
|
|
@@ -1440,15 +1688,15 @@ const renderOptions = {
|
|
|
1440
1688
|
if (props.tile.type === 'image') {
|
|
1441
1689
|
return <MyImageTile {...props} />;
|
|
1442
1690
|
}
|
|
1443
|
-
//
|
|
1691
|
+
// Keep the default behavior
|
|
1444
1692
|
return defaultRenderOptions.renderTileAs(props);
|
|
1445
1693
|
},
|
|
1446
1694
|
};
|
|
1447
1695
|
```
|
|
1448
1696
|
|
|
1449
|
-
###
|
|
1697
|
+
### Customizing the Long-Press Menu (new in 0.2.x)
|
|
1450
1698
|
|
|
1451
|
-
If you need to customize the style or behavior of the long
|
|
1699
|
+
If you need to customize the style or behavior of the long-press menu, you can override the `renderLongPressAs` function, for example:
|
|
1452
1700
|
|
|
1453
1701
|
```tsx
|
|
1454
1702
|
import { defaultRenderOptions, LongPressResult } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1474,16 +1722,16 @@ const renderOptions = {
|
|
|
1474
1722
|
};
|
|
1475
1723
|
```
|
|
1476
1724
|
|
|
1477
|
-
|
|
1725
|
+
The long-press menu features include:
|
|
1478
1726
|
|
|
1479
|
-
- **Copy
|
|
1480
|
-
- **Delete
|
|
1481
|
-
- **Multi-select**:
|
|
1482
|
-
- **Like/
|
|
1727
|
+
- **Copy message**: copy the text content to the clipboard
|
|
1728
|
+
- **Delete message**: delete a single message
|
|
1729
|
+
- **Multi-select**: enter multi-select mode, used together with MessageActionBar
|
|
1730
|
+
- **Like/Dislike**: give feedback on assistant messages (only available for assistant-role messages)
|
|
1483
1731
|
|
|
1484
|
-
###
|
|
1732
|
+
### Customizing Error Message Formatting (new in 0.2.x)
|
|
1485
1733
|
|
|
1486
|
-
If you need to customize
|
|
1734
|
+
If you need to customize how error messages are displayed, you can override the `formatErrorMessageAs` function, for example:
|
|
1487
1735
|
|
|
1488
1736
|
```tsx
|
|
1489
1737
|
import { defaultRenderOptions } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1491,49 +1739,49 @@ import { defaultRenderOptions } from '@ray-js/t-agent-ui-ray';
|
|
|
1491
1739
|
const renderOptions = {
|
|
1492
1740
|
...defaultRenderOptions,
|
|
1493
1741
|
formatErrorMessageAs: (message: string, code: string | undefined) => {
|
|
1494
|
-
// Return custom error
|
|
1742
|
+
// Return a custom error message based on the error code
|
|
1495
1743
|
if (code === 'network-offline') {
|
|
1496
|
-
return 'Network connection
|
|
1744
|
+
return 'Network connection error. Please check your network settings.';
|
|
1497
1745
|
}
|
|
1498
1746
|
if (code === 'timeout') {
|
|
1499
|
-
return 'Request
|
|
1747
|
+
return 'Request timed out. Please try again later.';
|
|
1500
1748
|
}
|
|
1501
|
-
// Use default error message
|
|
1749
|
+
// Use the default error message
|
|
1502
1750
|
return message;
|
|
1503
1751
|
},
|
|
1504
1752
|
};
|
|
1505
1753
|
```
|
|
1506
1754
|
|
|
1507
|
-
|
|
1755
|
+
The built-in supported error codes include:
|
|
1508
1756
|
|
|
1509
|
-
- `network-offline`:
|
|
1510
|
-
- `timeout`:
|
|
1511
|
-
- `invalid-params`:
|
|
1512
|
-
- `session-create-failed`:
|
|
1513
|
-
- `connection-closed`:
|
|
1514
|
-
-
|
|
1757
|
+
- `network-offline`: the network is disconnected
|
|
1758
|
+
- `timeout`: send timed out
|
|
1759
|
+
- `invalid-params`: invalid parameters
|
|
1760
|
+
- `session-create-failed`: connection failed
|
|
1761
|
+
- `connection-closed`: connection closed
|
|
1762
|
+
- and so on
|
|
1515
1763
|
|
|
1516
|
-
###
|
|
1764
|
+
### Custom Cards
|
|
1517
1765
|
|
|
1518
|
-
Cards
|
|
1766
|
+
Cards fall into three categories: built-in cards (`buildIn`), custom cards (`custom`), and low-code cards (`lowCode`). Low-code cards are still under development. Custom cards can be registered with your own card components via `customCardMap`.
|
|
1519
1767
|
|
|
1520
|
-
The data structure
|
|
1768
|
+
The card data structure is as follows:
|
|
1521
1769
|
|
|
1522
1770
|
```tsx
|
|
1523
1771
|
enum ChatCardType {
|
|
1524
|
-
CUSTOM = 'custom', // Custom
|
|
1525
|
-
BUILD_IN = 'buildIn', // Platform built-in
|
|
1526
|
-
LOW_CODE = 'lowCode', // Low-code
|
|
1772
|
+
CUSTOM = 'custom', // Custom cards available for business use
|
|
1773
|
+
BUILD_IN = 'buildIn', // Platform built-in cards
|
|
1774
|
+
LOW_CODE = 'lowCode', // Low-code cards
|
|
1527
1775
|
}
|
|
1528
1776
|
|
|
1529
1777
|
interface ChatCardObject<T = any> {
|
|
1530
|
-
cardCode: string; //
|
|
1531
|
-
cardType: ChatCardType; //
|
|
1532
|
-
cardData: T; //
|
|
1778
|
+
cardCode: string; // The code that uniquely identifies the card
|
|
1779
|
+
cardType: ChatCardType; // The card type
|
|
1780
|
+
cardData: T; // The data carried by the card
|
|
1533
1781
|
}
|
|
1534
1782
|
```
|
|
1535
1783
|
|
|
1536
|
-
|
|
1784
|
+
Registering a custom card:
|
|
1537
1785
|
|
|
1538
1786
|
```tsx
|
|
1539
1787
|
import {
|
|
@@ -1546,12 +1794,12 @@ import {
|
|
|
1546
1794
|
import { View, Text, Button } from '@ray-js/ray';
|
|
1547
1795
|
|
|
1548
1796
|
const MyCard: ChatCardComponent<{ title: string }, { clicked: boolean }> = props => {
|
|
1549
|
-
// If you need
|
|
1797
|
+
// If you need properties like agent, message, tile, emitTileEvent, you can use useTileProps
|
|
1550
1798
|
const { message, agent, tile, emitTileEvent } = useTileProps();
|
|
1551
1799
|
const { card, setCardState } = props;
|
|
1552
1800
|
const { cardData, cardState, cardCode } = card as ChatCardObject<{ title: string }>;
|
|
1553
1801
|
|
|
1554
|
-
// If you need to send a TTTAction, use useSendAction
|
|
1802
|
+
// If you need to send a TTTAction, you can use useSendAction
|
|
1555
1803
|
const sendAction = useSendAction();
|
|
1556
1804
|
|
|
1557
1805
|
return (
|
|
@@ -1560,12 +1808,12 @@ const MyCard: ChatCardComponent<{ title: string }, { clicked: boolean }> = props
|
|
|
1560
1808
|
<Button
|
|
1561
1809
|
onClick={() => {
|
|
1562
1810
|
sendAction({ type: 'sendMessage', blocks: [{ type: 'text', text: 'hello' }] });
|
|
1563
|
-
// If you
|
|
1564
|
-
// The second
|
|
1811
|
+
// If you need to update the card state, you can use setCardState
|
|
1812
|
+
// The second argument indicates whether to persist the state
|
|
1565
1813
|
setCardState({ clicked: true }, { persist: true });
|
|
1566
1814
|
}}
|
|
1567
1815
|
>
|
|
1568
|
-
Fill text into input
|
|
1816
|
+
Fill text into the input field
|
|
1569
1817
|
</Button>
|
|
1570
1818
|
</View>
|
|
1571
1819
|
);
|
|
@@ -1579,21 +1827,21 @@ const renderOptions = {
|
|
|
1579
1827
|
};
|
|
1580
1828
|
```
|
|
1581
1829
|
|
|
1582
|
-
###
|
|
1830
|
+
### Custom Blocks
|
|
1583
1831
|
|
|
1584
|
-
|
|
1832
|
+
The markdown renderer in `TextTile` supports custom blocks. You can register and render custom blocks via `customBlockTypes` and `renderCustomBlockAs`.
|
|
1585
1833
|
|
|
1586
|
-
The data structure
|
|
1834
|
+
The block data structure is as follows:
|
|
1587
1835
|
|
|
1588
1836
|
```tsx
|
|
1589
1837
|
export interface MarkdownBlock {
|
|
1590
1838
|
id: string;
|
|
1591
1839
|
type: string;
|
|
1592
|
-
children: string; //
|
|
1840
|
+
children: string; // The content inside the block
|
|
1593
1841
|
}
|
|
1594
1842
|
```
|
|
1595
1843
|
|
|
1596
|
-
|
|
1844
|
+
Registering a custom block:
|
|
1597
1845
|
|
|
1598
1846
|
```tsx
|
|
1599
1847
|
import { defaultRenderOptions, MarkdownBlock } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1611,12 +1859,12 @@ const renderOptions = {
|
|
|
1611
1859
|
</View>
|
|
1612
1860
|
);
|
|
1613
1861
|
}
|
|
1614
|
-
return defaultRenderOptions.renderCustomBlockAs(
|
|
1862
|
+
return defaultRenderOptions.renderCustomBlockAs(props);
|
|
1615
1863
|
},
|
|
1616
1864
|
};
|
|
1617
1865
|
```
|
|
1618
1866
|
|
|
1619
|
-
|
|
1867
|
+
Suppose the AI sends you markdown text containing a `fence` of type `my-block`. Since we registered `my-block` above, this `fence` is treated as a custom block.
|
|
1620
1868
|
|
|
1621
1869
|
````markdown
|
|
1622
1870
|
This is my custom block!
|
|
@@ -1626,32 +1874,24 @@ Hello, world!
|
|
|
1626
1874
|
```
|
|
1627
1875
|
````
|
|
1628
1876
|
|
|
1629
|
-
The
|
|
1877
|
+
The fence below is not registered, so it will not be rendered as a custom block — it's rendered as a regular code block.
|
|
1630
1878
|
|
|
1631
1879
|
```javascript
|
|
1632
1880
|
console.log('Hello, world!');
|
|
1633
1881
|
```
|
|
1634
1882
|
|
|
1635
|
-
```
|
|
1636
|
-
|
|
1637
1883
|
The rendered result is as follows:
|
|
1638
1884
|
|
|
1639
|
-
```
|
|
1640
|
-
|
|
1641
1885
|
This is my custom block!
|
|
1642
1886
|
This is My Block
|
|
1643
1887
|
Hello, world!
|
|
1644
|
-
The
|
|
1645
|
-
|
|
1646
|
-
---
|
|
1888
|
+
The fence below is not registered, so it will not be rendered as a custom block — it's rendered as a regular code block.
|
|
1647
1889
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
````
|
|
1890
|
+
console.log('Hello, world!');
|
|
1651
1891
|
|
|
1652
1892
|
### getStaticResourceBizType
|
|
1653
1893
|
|
|
1654
|
-
If your static resources need
|
|
1894
|
+
If your static resources need a `bizType`, you can get the `bizType` via `getStaticResourceBizType`.
|
|
1655
1895
|
|
|
1656
1896
|
```tsx
|
|
1657
1897
|
import { defaultRenderOptions } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1660,22 +1900,22 @@ const renderOptions = {
|
|
|
1660
1900
|
...defaultRenderOptions,
|
|
1661
1901
|
getStaticResourceBizType: (src: string, scene: string) => 'bizType',
|
|
1662
1902
|
};
|
|
1663
|
-
|
|
1903
|
+
```
|
|
1664
1904
|
|
|
1665
|
-
For different scenarios, you may
|
|
1905
|
+
For different scenarios, you may need different `bizType` values. You can return different `bizType` values based on `src` and `scene`.
|
|
1666
1906
|
|
|
1667
|
-
The built-in `scene`
|
|
1907
|
+
The built-in `scene` values are:
|
|
1668
1908
|
|
|
1669
|
-
- `image:view`
|
|
1670
|
-
- `image:upload`
|
|
1671
|
-
- `video:view`
|
|
1672
|
-
- `video:upload`
|
|
1673
|
-
- `videoThumb:view`
|
|
1674
|
-
- `videoThumb:upload`
|
|
1909
|
+
- `image:view` — image viewing
|
|
1910
|
+
- `image:upload` — image uploading
|
|
1911
|
+
- `video:view` — video viewing
|
|
1912
|
+
- `video:upload` — video uploading
|
|
1913
|
+
- `videoThumb:view` — video thumbnail viewing
|
|
1914
|
+
- `videoThumb:upload` — video thumbnail uploading
|
|
1675
1915
|
|
|
1676
|
-
###
|
|
1916
|
+
### Customizing Internationalization
|
|
1677
1917
|
|
|
1678
|
-
If you need to customize
|
|
1918
|
+
If you need to customize the internationalization in t-agent, you can override the `i18nTranslate` function, for example:
|
|
1679
1919
|
|
|
1680
1920
|
```tsx
|
|
1681
1921
|
import { defaultRenderOptions } from '@ray-js/t-agent-ui-ray';
|
|
@@ -1684,140 +1924,110 @@ const renderOptions = {
|
|
|
1684
1924
|
...defaultRenderOptions,
|
|
1685
1925
|
i18nTranslate: (key: string) => {
|
|
1686
1926
|
if (key === 'hello') {
|
|
1687
|
-
return '
|
|
1927
|
+
return 'Hello';
|
|
1688
1928
|
}
|
|
1689
|
-
// Use default
|
|
1929
|
+
// Use the default internationalization
|
|
1690
1930
|
return I18n.t(key);
|
|
1691
1931
|
},
|
|
1692
1932
|
};
|
|
1693
1933
|
```
|
|
1694
1934
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
| key | Usage
|
|
1698
|
-
| ---------------------------------------------------------- |
|
|
1699
|
-
| t-agent.build-in.button.create_scene_manually |
|
|
1700
|
-
| t-agent.build-in.button.enter_home_manage |
|
|
1701
|
-
| t-agent.build-in.button.enter_room_manage |
|
|
1702
|
-
| t-agent.build-in.button.enter_alarm_message |
|
|
1703
|
-
| t-agent.build-in.button.enter_home_message |
|
|
1704
|
-
| t-agent.build-in.button.enter_bulletin |
|
|
1705
|
-
| t-agent.build-in.button.enter_notification_setting |
|
|
1706
|
-
| t-agent.build-in.button.enter_personal_information |
|
|
1707
|
-
| t-agent.build-in.button.enter_account_security |
|
|
1708
|
-
| t-agent.build-in.button.enter_setting |
|
|
1709
|
-
| t-agent.build-in.button.enter_paring |
|
|
1710
|
-
| t-agent.build-in.button.enter_share_device |
|
|
1711
|
-
| t-agent.build-in.button.enter_faq_feedback |
|
|
1712
|
-
| t-agent.build-in.button.questionnaire_take |
|
|
1713
|
-
| t-agent.build-in.button.set_home_location |
|
|
1714
|
-
| t-agent.input.voice.require-permission | MessageInput switch to voice input
|
|
1715
|
-
| t-agent.input.upload.failed | MessageInput file upload
|
|
1716
|
-
| t-agent.input.asr.oninput.text.top | MessageInput ASR voice input
|
|
1717
|
-
| t-agent.input.asr.oninput.text.center | MessageInput ASR voice input
|
|
1718
|
-
| t-agent.input.asr.ptt | MessageInput ASR voice input
|
|
1719
|
-
| t-agent.input.asr.error.too-short | MessageInput ASR error
|
|
1720
|
-
| t-agent.input.asr.error.empty | MessageInput ASR error
|
|
1721
|
-
| t-agent.input.asr.error.unknown | MessageInput ASR error
|
|
1722
|
-
| t-agent.input.asr.error.timeout | MessageInput ASR error
|
|
1723
|
-
| t-agent.input.upload.source-type.camera | MessageInput file upload
|
|
1724
|
-
| t-agent.input.upload.source-type.camera.require-permission | MessageInput file upload
|
|
1725
|
-
| t-agent.input.upload.source-type.album | MessageInput file upload
|
|
1726
|
-
| t-agent.input.upload.source-type.album.require-permission | MessageInput file upload
|
|
1727
|
-
| t-agent.input.upload.image.max-reached | MessageInput file upload
|
|
1728
|
-
| t-agent.input.upload.video.max-reached | MessageInput file upload
|
|
1729
|
-
| t-agent.file-tile.unknown-filename | FileTile file display
|
|
1730
|
-
| t-agent.message.feedback.success | BubbleTile message
|
|
1731
|
-
| t-agent.message.bubble.aborted | BubbleTile message
|
|
1732
|
-
| t-agent.message.action.copy | BubbleTile long
|
|
1733
|
-
| t-agent.message.action.delete | BubbleTile long
|
|
1734
|
-
| t-agent.message.action.multi-select | BubbleTile long
|
|
1735
|
-
| t-agent.message.action.like | BubbleTile long
|
|
1736
|
-
| t-agent.message.action.unlike | BubbleTile long
|
|
1737
|
-
| t-agent.message.copy.success | BubbleTile copy success
|
|
1738
|
-
| t-agent.message.delete.success | BubbleTile delete success
|
|
1739
|
-
| t-agent.message.like.success | BubbleTile feedback
|
|
1740
|
-
| t-agent.message.unlike.success | BubbleTile feedback
|
|
1741
|
-
| t-agent.message.delete.title | BubbleTile delete
|
|
1742
|
-
| t-agent.message.delete.content | BubbleTile delete
|
|
1743
|
-
| t-agent.message.delete.confirm | BubbleTile delete
|
|
1744
|
-
| t-agent.message.delete.cancel | BubbleTile delete
|
|
1745
|
-
| t-agent.message.clear-history.title | MessageActionBar clear history
|
|
1746
|
-
| t-agent.message.clear-history.content | MessageActionBar clear history
|
|
1747
|
-
| t-agent.message.clear-history.button | MessageActionBar clear history
|
|
1748
|
-
| t-agent.message.multi-select-delete.title | MessageActionBar multi-select delete
|
|
1749
|
-
| t-agent.message.multi-select-delete.content | MessageActionBar multi-select delete
|
|
1750
|
-
| t-agent.execute-card-tile.execution.success | ExecuteCardTile execution result
|
|
1751
|
-
| t-agent.execute-card-tile.execution.failed | ExecuteCardTile execution result
|
|
1752
|
-
| t-agent.execute-card-tile.scene.invalid | ExecuteCardTile scene status
|
|
1753
|
-
| t-agent.execute-card-tile.delete | ExecuteCardTile button
|
|
1754
|
-
| t-agent.execute-card-tile.execute | ExecuteCardTile button
|
|
1755
|
-
| t-agent.execute-card-tile.switch.scene.state | ExecuteCardTile operation
|
|
1756
|
-
| t-agent.operate-card-tile.open.device.failed | OperateCardTile operation result
|
|
1757
|
-
| t-agent.operate-card-tile.open.scene.failed | OperateCardTile operation result
|
|
1758
|
-
| t-agent.operate-card-tile.operation.impact | OperateCardTile title
|
|
1759
|
-
| t-agent.operate-card-tile.hide.details | OperateCardTile button
|
|
1760
|
-
| t-agent.operate-card-tile.view.details | OperateCardTile button
|
|
1761
|
-
| t-agent.operate-card-tile.device.move.desc | OperateCardTile device move
|
|
1762
|
-
| t-agent.operate-card-tile.device.rename.desc | OperateCardTile device rename
|
|
1763
|
-
| t-agent.operate-card-tile.device.count | OperateCardTile device count
|
|
1764
|
-
| t-agent.operate-card-tile.scene.count | OperateCardTile scene count
|
|
1765
|
-
| t-agent.operate-card-tile.home.count | OperateCardTile home count
|
|
1766
|
-
| t-agent.operate-card-tile.room.count | OperateCardTile room count
|
|
1767
|
-
| t-agent.operate-card-tile.group.count | OperateCardTile group count
|
|
1768
|
-
| t-agent.operate-card-tile.description.format | OperateCardTile description format
|
|
1769
|
-
| t-agent.operate-card-tile.description.separator | OperateCardTile description separator
|
|
1770
|
-
| t-agent.expand.tab.device | ExpandTile tab
|
|
1771
|
-
| t-agent.expand.tab.scene | ExpandTile tab
|
|
1772
|
-
| t-agent.expand.tab.more | ExpandTile tab
|
|
1773
|
-
| t-agent.expand.execution.success | ExpandTile execution result
|
|
1774
|
-
| t-agent.expand.execution.failed | ExpandTile execution result
|
|
1775
|
-
| t-agent.expand.device.rename | ExpandTile device rename
|
|
1776
|
-
| t-agent.expand.scene.rename | ExpandTile scene rename
|
|
1777
|
-
| t-agent.expand.scene.one-click | ExpandTile scene type
|
|
1778
|
-
| t-agent.expand.scene.auto | ExpandTile scene type
|
|
1779
|
-
| t-agent.expand.no.details | ExpandTile
|
|
1780
|
-
| t-agent.error.unknown-error | Error message
|
|
1781
|
-
| t-agent.error.network-offline | Error message
|
|
1782
|
-
| t-agent.error.invalid-params | Error message
|
|
1783
|
-
| t-agent.error.session-create-failed | Error message
|
|
1784
|
-
| t-agent.error.connection-closed | Error message
|
|
1785
|
-
| t-agent.error.event-exists | Error message
|
|
1786
|
-
| t-agent.error.event-disposed | Error message
|
|
1787
|
-
| t-agent.error.event-closed | Error message
|
|
1788
|
-
| t-agent.error.event-aborted | Error message
|
|
1789
|
-
| t-agent.error.event-write-failed | Error message
|
|
1790
|
-
| t-agent.error.event-no-data-code | Error message
|
|
1791
|
-
| t-agent.error.stream-exists | Error message
|
|
1792
|
-
| t-agent.error.timeout | Error message
|
|
1793
|
-
| t-agent.error.asr-empty | Error message
|
|
1794
|
-
|
|
1795
|
-
# Change Log
|
|
1796
|
-
|
|
1797
|
-
## Version 0.2.x
|
|
1798
|
-
|
|
1799
|
-
### @ray-js/t-agent
|
|
1800
|
-
|
|
1801
|
-
- **Hook Mechanism Enhancement**: Added new lifecycle hooks such as `onMessageFeedback` and `onClearHistory`
|
|
1802
|
-
- **Message State Management**: Optimized message state management, providing more precise message state control
|
|
1803
|
-
- **Error Handling**: Enhanced error handling mechanism, supporting more detailed error information and error classification
|
|
1804
|
-
- **Performance Optimization**: Optimized memory management and garbage collection mechanisms
|
|
1805
|
-
|
|
1806
|
-
### @ray-js/t-agent-plugin-aistream
|
|
1807
|
-
|
|
1808
|
-
- **New Plugin**: Replaces the deprecated assistant plugin, providing more powerful functionality
|
|
1809
|
-
- **Connection Optimization**: Added `earlyStart` parameter, supporting early connection establishment to reduce first response time
|
|
1810
|
-
- **Token Management**: Optimized Token acquisition mechanism, supporting custom `tokenOptions`
|
|
1811
|
-
- **Speech Recognition**: Added AsrAgent speech recognition functionality, supporting real-time speech-to-text
|
|
1812
|
-
- **Mock Mechanism**: Improved mock mechanism, supporting more flexible testing scenarios
|
|
1813
|
-
- **Multi-modal Support**: Default support for various input types including text, images, and voice
|
|
1814
|
-
|
|
1815
|
-
### @ray-js/t-agent-ui-ray
|
|
1816
|
-
|
|
1817
|
-
- **Message Action Bar**: Added MessageActionBar component, supporting multi-select operations and batch deletion
|
|
1818
|
-
- **Virtual Scrolling**: Integrated LazyScrollView, providing virtual scrolling and performance optimization
|
|
1819
|
-
- **Internationalization System**: Complete internationalization system, supporting 8 languages including Simplified Chinese, Traditional Chinese, English, Japanese, etc.
|
|
1820
|
-
- **Translation Hook**: Added useTranslate Hook, simplifying multilingual usage
|
|
1821
|
-
- **Custom Rendering**: Extended renderOptions, supporting more custom rendering options
|
|
1822
|
-
- **Interaction Optimization**: Optimized long press menu functionality, supporting copy, delete, multi-select, like and other operations
|
|
1823
|
-
- **UI Enhancement**: Added multilingual key-value pairs, covering all UI interaction scenarios
|
|
1935
|
+
The built-in i18n keys are as follows:
|
|
1936
|
+
|
|
1937
|
+
| key | Usage | Meaning |
|
|
1938
|
+
| ---------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------- |
|
|
1939
|
+
| t-agent.build-in.button.create_scene_manually | ButtonTile built-in button | Create scene manually |
|
|
1940
|
+
| t-agent.build-in.button.enter_home_manage | ButtonTile built-in button | Enter "Home Management" |
|
|
1941
|
+
| t-agent.build-in.button.enter_room_manage | ButtonTile built-in button | Enter "Room Management" |
|
|
1942
|
+
| t-agent.build-in.button.enter_alarm_message | ButtonTile built-in button | Enter "Alarm Message List" |
|
|
1943
|
+
| t-agent.build-in.button.enter_home_message | ButtonTile built-in button | Enter "Home Message List" |
|
|
1944
|
+
| t-agent.build-in.button.enter_bulletin | ButtonTile built-in button | Enter "Notification Message List" |
|
|
1945
|
+
| t-agent.build-in.button.enter_notification_setting | ButtonTile built-in button | Enter "Message Push Settings" |
|
|
1946
|
+
| t-agent.build-in.button.enter_personal_information | ButtonTile built-in button | Enter "Personal Profile" |
|
|
1947
|
+
| t-agent.build-in.button.enter_account_security | ButtonTile built-in button | Enter "Account & Security" |
|
|
1948
|
+
| t-agent.build-in.button.enter_setting | ButtonTile built-in button | Enter "General Settings" |
|
|
1949
|
+
| t-agent.build-in.button.enter_paring | ButtonTile built-in button | Enter "Device Pairing" |
|
|
1950
|
+
| t-agent.build-in.button.enter_share_device | ButtonTile built-in button | Enter "Device Sharing" |
|
|
1951
|
+
| t-agent.build-in.button.enter_faq_feedback | ButtonTile built-in button | Enter "FAQ & Feedback" |
|
|
1952
|
+
| t-agent.build-in.button.questionnaire_take | ButtonTile built-in button | Fill out questionnaire |
|
|
1953
|
+
| t-agent.build-in.button.set_home_location | ButtonTile built-in button | Set home location |
|
|
1954
|
+
| t-agent.input.voice.require-permission | MessageInput switch to voice input | Recording permission required |
|
|
1955
|
+
| t-agent.input.upload.failed | MessageInput file upload | File upload failed |
|
|
1956
|
+
| t-agent.input.asr.oninput.text.top | MessageInput ASR voice input | I'm listening, please speak |
|
|
1957
|
+
| t-agent.input.asr.oninput.text.center | MessageInput ASR voice input | Release to send, swipe up to cancel |
|
|
1958
|
+
| t-agent.input.asr.ptt | MessageInput ASR voice input | Hold to talk |
|
|
1959
|
+
| t-agent.input.asr.error.too-short | MessageInput ASR error | Speech too short |
|
|
1960
|
+
| t-agent.input.asr.error.empty | MessageInput ASR error | No text recognized from speech |
|
|
1961
|
+
| t-agent.input.asr.error.unknown | MessageInput ASR error | Speech recognition failed |
|
|
1962
|
+
| t-agent.input.asr.error.timeout | MessageInput ASR error | Speech recognition reached the time limit; sending now |
|
|
1963
|
+
| t-agent.input.upload.source-type.camera | MessageInput file upload | Take photo |
|
|
1964
|
+
| t-agent.input.upload.source-type.camera.require-permission | MessageInput file upload | Taking a photo requires camera permission; enable it in Settings |
|
|
1965
|
+
| t-agent.input.upload.source-type.album | MessageInput file upload | Choose from album |
|
|
1966
|
+
| t-agent.input.upload.source-type.album.require-permission | MessageInput file upload | Choosing from album requires album permission; enable it in Settings |
|
|
1967
|
+
| t-agent.input.upload.image.max-reached | MessageInput file upload | Image upload limit reached |
|
|
1968
|
+
| t-agent.input.upload.video.max-reached | MessageInput file upload | Video upload limit reached |
|
|
1969
|
+
| t-agent.file-tile.unknown-filename | FileTile file display | File |
|
|
1970
|
+
| t-agent.message.feedback.success | BubbleTile message rating | Feedback submitted |
|
|
1971
|
+
| t-agent.message.bubble.aborted | BubbleTile message | Aborted by user |
|
|
1972
|
+
| t-agent.message.action.copy | BubbleTile long-press menu | Copy message |
|
|
1973
|
+
| t-agent.message.action.delete | BubbleTile long-press menu | Delete message |
|
|
1974
|
+
| t-agent.message.action.multi-select | BubbleTile long-press menu | Multi-select |
|
|
1975
|
+
| t-agent.message.action.like | BubbleTile long-press menu | Like message |
|
|
1976
|
+
| t-agent.message.action.unlike | BubbleTile long-press menu | Dislike message |
|
|
1977
|
+
| t-agent.message.copy.success | BubbleTile copy success | Copied successfully |
|
|
1978
|
+
| t-agent.message.delete.success | BubbleTile delete success | Deleted successfully |
|
|
1979
|
+
| t-agent.message.like.success | BubbleTile feedback | Liked successfully |
|
|
1980
|
+
| t-agent.message.unlike.success | BubbleTile feedback | Like removed successfully |
|
|
1981
|
+
| t-agent.message.delete.title | BubbleTile delete dialog title | Delete message |
|
|
1982
|
+
| t-agent.message.delete.content | BubbleTile delete dialog content | Are you sure you want to delete this message? |
|
|
1983
|
+
| t-agent.message.delete.confirm | BubbleTile delete dialog confirm | Confirm |
|
|
1984
|
+
| t-agent.message.delete.cancel | BubbleTile delete dialog cancel | Cancel |
|
|
1985
|
+
| t-agent.message.clear-history.title | MessageActionBar clear history | Clear history |
|
|
1986
|
+
| t-agent.message.clear-history.content | MessageActionBar clear history | Are you sure you want to clear the history? |
|
|
1987
|
+
| t-agent.message.clear-history.button | MessageActionBar clear history | Clear history |
|
|
1988
|
+
| t-agent.message.multi-select-delete.title | MessageActionBar multi-select delete | Delete selected messages |
|
|
1989
|
+
| t-agent.message.multi-select-delete.content | MessageActionBar multi-select delete | Are you sure you want to delete the selected messages? |
|
|
1990
|
+
| t-agent.execute-card-tile.execution.success | ExecuteCardTile execution result | Execution succeeded |
|
|
1991
|
+
| t-agent.execute-card-tile.execution.failed | ExecuteCardTile execution result | Execution failed |
|
|
1992
|
+
| t-agent.execute-card-tile.scene.invalid | ExecuteCardTile scene status | Scene invalid |
|
|
1993
|
+
| t-agent.execute-card-tile.delete | ExecuteCardTile button | Delete |
|
|
1994
|
+
| t-agent.execute-card-tile.execute | ExecuteCardTile button | Execute |
|
|
1995
|
+
| t-agent.execute-card-tile.switch.scene.state | ExecuteCardTile operation | Toggle scene state |
|
|
1996
|
+
| t-agent.operate-card-tile.open.device.failed | OperateCardTile operation result | Failed to open device |
|
|
1997
|
+
| t-agent.operate-card-tile.open.scene.failed | OperateCardTile operation result | Failed to open scene |
|
|
1998
|
+
| t-agent.operate-card-tile.operation.impact | OperateCardTile title | This operation affects: |
|
|
1999
|
+
| t-agent.operate-card-tile.hide.details | OperateCardTile button | Hide details |
|
|
2000
|
+
| t-agent.operate-card-tile.view.details | OperateCardTile button | View details |
|
|
2001
|
+
| t-agent.operate-card-tile.device.move.desc | OperateCardTile device move | Device "{device}" moved to "{room}" |
|
|
2002
|
+
| t-agent.operate-card-tile.device.rename.desc | OperateCardTile device rename | Device "{oldName}" renamed to "{newName}" |
|
|
2003
|
+
| t-agent.operate-card-tile.device.count | OperateCardTile device count | {count} device(s) |
|
|
2004
|
+
| t-agent.operate-card-tile.scene.count | OperateCardTile scene count | {count} scene(s) |
|
|
2005
|
+
| t-agent.operate-card-tile.home.count | OperateCardTile home count | {count} home(s) |
|
|
2006
|
+
| t-agent.operate-card-tile.room.count | OperateCardTile room count | {count} room(s) |
|
|
2007
|
+
| t-agent.operate-card-tile.group.count | OperateCardTile group count | {count} group(s) |
|
|
2008
|
+
| t-agent.operate-card-tile.description.format | OperateCardTile description format | {items}. |
|
|
2009
|
+
| t-agent.operate-card-tile.description.separator | OperateCardTile description separator | , |
|
|
2010
|
+
| t-agent.expand.tab.device | ExpandTile tab | Devices |
|
|
2011
|
+
| t-agent.expand.tab.scene | ExpandTile tab | Scenes |
|
|
2012
|
+
| t-agent.expand.tab.more | ExpandTile tab | Other |
|
|
2013
|
+
| t-agent.expand.execution.success | ExpandTile execution result | Execution succeeded |
|
|
2014
|
+
| t-agent.expand.execution.failed | ExpandTile execution result | Execution failed |
|
|
2015
|
+
| t-agent.expand.device.rename | ExpandTile device rename | {oldName} renamed to {newName} |
|
|
2016
|
+
| t-agent.expand.scene.rename | ExpandTile scene rename | {oldName} renamed to {newName} |
|
|
2017
|
+
| t-agent.expand.scene.one-click | ExpandTile scene type | One-click execution |
|
|
2018
|
+
| t-agent.expand.scene.auto | ExpandTile scene type | Automatic execution |
|
|
2019
|
+
| t-agent.expand.no.details | ExpandTile detail display | No details to display |
|
|
2020
|
+
| t-agent.error.unknown-error | Error message | Unknown error |
|
|
2021
|
+
| t-agent.error.network-offline | Error message | Network disconnected, please check your connection |
|
|
2022
|
+
| t-agent.error.invalid-params | Error message | Invalid parameters, please try again |
|
|
2023
|
+
| t-agent.error.session-create-failed | Error message | Connection failed, please try again |
|
|
2024
|
+
| t-agent.error.connection-closed | Error message | Connection closed, please try again |
|
|
2025
|
+
| t-agent.error.event-exists | Error message | Message sending error, please try again later |
|
|
2026
|
+
| t-agent.error.event-disposed | Error message | Message sending error, please try again later |
|
|
2027
|
+
| t-agent.error.event-closed | Error message | Message sending error, please try again later |
|
|
2028
|
+
| t-agent.error.event-aborted | Error message | Message aborted |
|
|
2029
|
+
| t-agent.error.event-write-failed | Error message | Message sending error, please try again later |
|
|
2030
|
+
| t-agent.error.event-no-data-code | Error message | Message sending error, please try again later |
|
|
2031
|
+
| t-agent.error.stream-exists | Error message | Message sending error, please try again later |
|
|
2032
|
+
| t-agent.error.timeout | Error message | Send timed out |
|
|
2033
|
+
| t-agent.error.asr-empty | Error message | Speech recognition result is empty |
|