@ray-js/t-agent 0.2.7 → 0.2.8-beta.2
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 +286 -104
- package/README.md +249 -88
- package/dist/chat/ChatBubbleTile.d.ts +2 -2
- package/dist/chat/ChatMessage.js +7 -5
- package/dist/chat/ChatSession.d.ts +2 -2
- package/dist/chat/ChatSession.js +0 -5
- package/dist/chat/deepmerge.d.ts +27 -0
- package/dist/chat/deepmerge.js +141 -0
- package/dist/chat/index.d.ts +1 -0
- package/dist/chat/index.js +3 -1
- package/dist/chat/json.js +6 -1
- package/dist/chat/types.js +2 -0
- package/dist/chat/utils.d.ts +0 -1
- package/dist/chat/utils.js +0 -24
- package/dist/index.js +1 -0
- package/dist/plugins/ui.d.ts +2 -2
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ yarn add @ray-js/t-agent @ray-js/t-agent-plugin-aistream @ray-js/t-agent-ui-ray
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
> When using MCP features, `AIStreamKit` must be version `2.2.1` or higher.
|
|
32
|
+
|
|
31
33
|
## package.json Dependency Requirements
|
|
32
34
|
|
|
33
35
|
```json
|
|
@@ -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 />
|
|
@@ -785,6 +798,8 @@ Methods:
|
|
|
785
798
|
- `options.sendBy` Sender role, defaults to 'user'
|
|
786
799
|
- `options.responseBy` Responder role, defaults to 'assistant'
|
|
787
800
|
- `options.userData` Optional user data
|
|
801
|
+
- `agent.plugins.aiStream.removeMessage(message)` Delete a history message
|
|
802
|
+
- `agent.plugins.aiStream.clearAllMessages()` Clear all messages and local history in the current session
|
|
788
803
|
- `agent.plugins.aiStream.getChatId()` Get the current session's chatId, returns Promise<string>
|
|
789
804
|
|
|
790
805
|
Hooks:
|
|
@@ -800,7 +815,7 @@ Hooks:
|
|
|
800
815
|
- `status` Message status
|
|
801
816
|
- `result.text` Text content, can be modified
|
|
802
817
|
- `onSkillCompose` Triggered when receiving skill data, used for handling skill rendering
|
|
803
|
-
- `skill`
|
|
818
|
+
- `skill` Current skill data (ReceivedTextSkillPacketBody)
|
|
804
819
|
- `respMsg` Response message
|
|
805
820
|
- `result.messages` Message list
|
|
806
821
|
- `onSkillsEnd` Triggered when all skills processing is complete
|
|
@@ -821,8 +836,99 @@ Hooks:
|
|
|
821
836
|
- `data.blocks` When type is 'start-event', contains the input blocks for this send
|
|
822
837
|
- `result.userData` Returned user data object, will be merged and sent to the AI platform
|
|
823
838
|
|
|
839
|
+
### withBuildIn Plugin
|
|
840
|
+
|
|
841
|
+
Offers built-in features including smart home device control and knowledge base search.
|
|
842
|
+
|
|
843
|
+
**Supported Skills**:
|
|
844
|
+
|
|
845
|
+
- **Smart Home**: Device control and scene management
|
|
846
|
+
- **Knowledge Base Search**: Related document display
|
|
847
|
+
|
|
848
|
+
### withMCP Plugin
|
|
849
|
+
|
|
850
|
+
Provides MCP service exposure capability so the Agent can call tools implemented inside the mini-program, such as operating Bluetooth devices, calling custom APIs, or reading local files. Before using it, enable "Device MCP" on the agent node. In addition, MCP tool names must start with `device.`.
|
|
851
|
+
|
|
852
|
+

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

|
|
929
|
+
|
|
930
|
+
**Pass custom variables in the mini-program**:
|
|
931
|
+
|
|
826
932
|
```tsx
|
|
827
933
|
const agent = createChatAgent(
|
|
828
934
|
withUI(),
|
|
@@ -834,20 +940,28 @@ const agent = createChatAgent(
|
|
|
834
940
|
agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
835
941
|
// Pass user information when creating a session
|
|
836
942
|
if (type === 'create-session') {
|
|
837
|
-
result.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
943
|
+
result.userData = {
|
|
944
|
+
sessionAttributes: {
|
|
945
|
+
'custom.param': {
|
|
946
|
+
'custom.app.test_me': {
|
|
947
|
+
// The parameter name configured on the platform
|
|
948
|
+
value: `with value test me ${type} ${Date.now()}`,
|
|
949
|
+
},
|
|
950
|
+
},
|
|
841
951
|
},
|
|
842
952
|
};
|
|
843
953
|
return;
|
|
844
954
|
}
|
|
845
|
-
// Pass dynamic context
|
|
955
|
+
// Pass dynamic context every time a message is sent
|
|
846
956
|
if (type === 'start-event') {
|
|
847
|
-
result.
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
957
|
+
result.userData = {
|
|
958
|
+
sessionAttributes: {
|
|
959
|
+
'custom.param': {
|
|
960
|
+
'custom.app.test_me': {
|
|
961
|
+
// The parameter name configured on the platform
|
|
962
|
+
value: `with value test me ${type} ${Date.now()}`,
|
|
963
|
+
},
|
|
964
|
+
},
|
|
851
965
|
},
|
|
852
966
|
};
|
|
853
967
|
return;
|
|
@@ -855,15 +969,6 @@ agent.plugins.aiStream.onUserDataRead((type, data, result) => {
|
|
|
855
969
|
});
|
|
856
970
|
```
|
|
857
971
|
|
|
858
|
-
### withBuildIn Plugin
|
|
859
|
-
|
|
860
|
-
Offers built-in features including smart home device control and knowledge base search.
|
|
861
|
-
|
|
862
|
-
**Supported Skills**:
|
|
863
|
-
|
|
864
|
-
- **Smart Home**: Device control and scene management
|
|
865
|
-
- **Knowledge Base Search**: Related document display
|
|
866
|
-
|
|
867
972
|
## Mock Mechanism
|
|
868
973
|
|
|
869
974
|
To facilitate development, we offer a mock mechanism allowing mock data to be used without connecting to applet AI platforms.
|
|
@@ -913,6 +1018,92 @@ mock.hooks.hook('asrDetection', context => {
|
|
|
913
1018
|
});
|
|
914
1019
|
```
|
|
915
1020
|
|
|
1021
|
+
### mock MCP
|
|
1022
|
+
|
|
1023
|
+
The recommended approach is to decide which MCP tool to call in the mock `sendToAIStream` hook based on the input content, then directly run the full MCP call chain with `context.callMCPTool()`.
|
|
1024
|
+
|
|
1025
|
+
```tsx
|
|
1026
|
+
import { mock } from '@ray-js/t-agent-plugin-aistream';
|
|
1027
|
+
|
|
1028
|
+
const getToolCall = (text: string) => {
|
|
1029
|
+
if (text.includes('error') || text.includes('failed') || text.includes('exception')) {
|
|
1030
|
+
return {
|
|
1031
|
+
name: 'device.home.energy.summary.fail',
|
|
1032
|
+
arguments: {
|
|
1033
|
+
reason: 'mock-error-case',
|
|
1034
|
+
},
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
if (text.includes('energy') || text.includes('power') || text.includes('data')) {
|
|
1039
|
+
return {
|
|
1040
|
+
name: 'device.home.energy.summary.get',
|
|
1041
|
+
arguments: {
|
|
1042
|
+
period: 'today',
|
|
1043
|
+
},
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
return {
|
|
1048
|
+
name: 'device.app.open',
|
|
1049
|
+
arguments: {
|
|
1050
|
+
category: 'music',
|
|
1051
|
+
},
|
|
1052
|
+
};
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
export const setupMockMCP = () => {
|
|
1056
|
+
mock.hooks.hook('sendToAIStream', async context => {
|
|
1057
|
+
const text = context.data
|
|
1058
|
+
.filter(item => item.type === 'text')
|
|
1059
|
+
.map(item => item.text)
|
|
1060
|
+
.join(' ');
|
|
1061
|
+
|
|
1062
|
+
if (!/mcp|app|energy|power|data|error|failed|exception/i.test(text)) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const toolCall = getToolCall(text);
|
|
1067
|
+
|
|
1068
|
+
await context.writeText(`MCP mock is calling ${toolCall.name}...`);
|
|
1069
|
+
|
|
1070
|
+
try {
|
|
1071
|
+
const result = await context.callMCPTool(toolCall.name, toolCall.arguments, {
|
|
1072
|
+
delayMs: 80,
|
|
1073
|
+
});
|
|
1074
|
+
await context.writeText(
|
|
1075
|
+
`Tool ${toolCall.name} returned: ${
|
|
1076
|
+
typeof result === 'string' ? result : JSON.stringify(result == null ? {} : result)
|
|
1077
|
+
}`
|
|
1078
|
+
);
|
|
1079
|
+
} catch (error) {
|
|
1080
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1081
|
+
await context.writeText(`MCP mock received a tool error: ${message}`);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
await context.end();
|
|
1085
|
+
});
|
|
1086
|
+
};
|
|
1087
|
+
```
|
|
1088
|
+
|
|
1089
|
+
Register it once before creating the agent:
|
|
1090
|
+
|
|
1091
|
+
```tsx
|
|
1092
|
+
const createAgent = () => {
|
|
1093
|
+
setupMockMCP();
|
|
1094
|
+
|
|
1095
|
+
return createChatAgent(
|
|
1096
|
+
withUI(),
|
|
1097
|
+
withAIStream({
|
|
1098
|
+
agentId: 'your-agent-id',
|
|
1099
|
+
}),
|
|
1100
|
+
withMCP({
|
|
1101
|
+
createServer: () => server,
|
|
1102
|
+
})
|
|
1103
|
+
);
|
|
1104
|
+
};
|
|
1105
|
+
```
|
|
1106
|
+
|
|
916
1107
|
## Additional Utils Tools (Currently under development)
|
|
917
1108
|
|
|
918
1109
|
### AbortController
|
|
@@ -1791,33 +1982,3 @@ Below are the built-in multilingual keys:
|
|
|
1791
1982
|
| t-agent.error.stream-exists | Error message | Message sending error, please try again later |
|
|
1792
1983
|
| t-agent.error.timeout | Error message | Send timeout |
|
|
1793
1984
|
| t-agent.error.asr-empty | Error message | Speech recognition result is empty |
|
|
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
|
|
@@ -29,7 +29,7 @@ export default class ChatBubbleTile extends ChatTile<BubbleTileData> {
|
|
|
29
29
|
id: string;
|
|
30
30
|
type: string;
|
|
31
31
|
locked: boolean;
|
|
32
|
-
children: import("./types").ChatTileObject
|
|
33
|
-
fallback?: import("./types").TipTileData
|
|
32
|
+
children: import("./types").ChatTileObject[];
|
|
33
|
+
fallback?: import("./types").TipTileData;
|
|
34
34
|
};
|
|
35
35
|
}
|
package/dist/chat/ChatMessage.js
CHANGED
|
@@ -8,7 +8,8 @@ import "core-js/modules/web.dom-collections.iterator.js";
|
|
|
8
8
|
import { ChatMessageStatus } from './types';
|
|
9
9
|
import ChatTile from './ChatTile';
|
|
10
10
|
import ChatBubbleTile from './ChatBubbleTile';
|
|
11
|
-
import { deepCloneToPlainObject,
|
|
11
|
+
import { deepCloneToPlainObject, generateId } from './utils';
|
|
12
|
+
import { deepmerge } from './deepmerge';
|
|
12
13
|
import { getLogger } from './Logger';
|
|
13
14
|
export const logger = getLogger('TAgent/ChatAgent');
|
|
14
15
|
export default class ChatMessage {
|
|
@@ -65,7 +66,7 @@ export default class ChatMessage {
|
|
|
65
66
|
show() {
|
|
66
67
|
return this.agent.runWithCatchError(async () => {
|
|
67
68
|
if (this._isShow) {
|
|
68
|
-
|
|
69
|
+
logger.warn('message is already show');
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
72
|
await this.agent.hooks.callHook('onMessageChange:before', 'show', this);
|
|
@@ -78,7 +79,7 @@ export default class ChatMessage {
|
|
|
78
79
|
update() {
|
|
79
80
|
return this.agent.runWithCatchError(async () => {
|
|
80
81
|
if (!this._isShow) {
|
|
81
|
-
|
|
82
|
+
logger.warn('message is not show');
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
85
|
await this.agent.hooks.callHook('onMessageChange:before', 'update', this);
|
|
@@ -93,12 +94,13 @@ export default class ChatMessage {
|
|
|
93
94
|
remove() {
|
|
94
95
|
return this.agent.runWithCatchError(async () => {
|
|
95
96
|
if (!this._isShow) {
|
|
96
|
-
|
|
97
|
+
logger.warn('message is not show');
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
99
100
|
await this.agent.hooks.callHook('onMessageChange:before', 'remove', this);
|
|
100
101
|
await this.agent.hooks.callHook('onMessageChange', 'remove', this);
|
|
101
102
|
this.agent.session.unbindMessage(this);
|
|
103
|
+
this._isShow = false;
|
|
102
104
|
await this.agent.hooks.callHook('onMessageChange:after', 'remove', this);
|
|
103
105
|
});
|
|
104
106
|
}
|
|
@@ -146,7 +148,7 @@ export default class ChatMessage {
|
|
|
146
148
|
if (override) {
|
|
147
149
|
this.meta = meta;
|
|
148
150
|
} else {
|
|
149
|
-
this.meta =
|
|
151
|
+
this.meta = deepmerge(this.meta, meta);
|
|
150
152
|
}
|
|
151
153
|
return this;
|
|
152
154
|
}
|
|
@@ -14,7 +14,7 @@ export default class ChatSession {
|
|
|
14
14
|
constructor(agent: ChatAgent);
|
|
15
15
|
initValue: (key: string, value: any) => void;
|
|
16
16
|
set: (key: string, value: any) => Promise<void>;
|
|
17
|
-
get: <T = any>(key: string, defaultValue?: T
|
|
17
|
+
get: <T = any>(key: string, defaultValue?: T) => any;
|
|
18
18
|
getData: () => Record<string, any>;
|
|
19
19
|
initMessages: (messages: ChatMessage[]) => void;
|
|
20
20
|
getTileById: (id: string) => ChatTile<any> | undefined;
|
|
@@ -22,7 +22,7 @@ export default class ChatSession {
|
|
|
22
22
|
unbindTile: (tile: ChatTile) => void;
|
|
23
23
|
bindMessage: (message: ChatMessage) => void;
|
|
24
24
|
unbindMessage: (message: ChatMessage) => void;
|
|
25
|
-
onChange: (fn: ChatSessionHooks[
|
|
25
|
+
onChange: (fn: ChatSessionHooks["onChange"]) => () => void;
|
|
26
26
|
getLatestMessage: () => ChatMessage | undefined;
|
|
27
27
|
dispose: () => Promise<void>;
|
|
28
28
|
}
|
package/dist/chat/ChatSession.js
CHANGED
|
@@ -100,10 +100,5 @@ export default class ChatSession {
|
|
|
100
100
|
});
|
|
101
101
|
this.agent = agent;
|
|
102
102
|
this.hooks = createHooks();
|
|
103
|
-
const hooks = ['onChange'];
|
|
104
|
-
for (let i = 0; i < hooks.length; i++) {
|
|
105
|
-
const hook = hooks[i];
|
|
106
|
-
this[hook] = fn => this.hooks.hook(hook, fn);
|
|
107
|
-
}
|
|
108
103
|
}
|
|
109
104
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type PlainObject = Record<string, unknown>;
|
|
2
|
+
type PropertyKeyLike = string | symbol;
|
|
3
|
+
type KeyGetter = (value: PlainObject) => PropertyKeyLike[];
|
|
4
|
+
type IsMergeableObject = (value: unknown) => boolean;
|
|
5
|
+
type CloneFn = <T>(value: T) => T;
|
|
6
|
+
type DeepMergePairFn = <T, U>(target: T, source: U) => any;
|
|
7
|
+
type DeepMergeFn = (...args: any[]) => any;
|
|
8
|
+
type MergeArrayFn = (target: any[], source: any[]) => any[];
|
|
9
|
+
type CloneProtoObjectFn = <T extends PlainObject>(target: T) => T;
|
|
10
|
+
interface MergeArrayUtils {
|
|
11
|
+
clone: CloneFn;
|
|
12
|
+
deepmerge: DeepMergePairFn;
|
|
13
|
+
getKeys: KeyGetter;
|
|
14
|
+
isMergeableObject: IsMergeableObject;
|
|
15
|
+
}
|
|
16
|
+
interface DeepMergeOptions {
|
|
17
|
+
all?: boolean;
|
|
18
|
+
symbols?: boolean;
|
|
19
|
+
onlyDefinedProperties?: boolean;
|
|
20
|
+
cloneProtoObject?: CloneProtoObjectFn;
|
|
21
|
+
isMergeableObject?: IsMergeableObject;
|
|
22
|
+
mergeArray?: (utils: MergeArrayUtils) => MergeArrayFn;
|
|
23
|
+
}
|
|
24
|
+
declare function defaultIsMergeableObjectFactory(): IsMergeableObject;
|
|
25
|
+
export declare function deepmergeConstructor(options?: DeepMergeOptions): DeepMergeFn;
|
|
26
|
+
export declare const deepmerge: DeepMergeFn;
|
|
27
|
+
export { defaultIsMergeableObjectFactory as isMergeableObject };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import "core-js/modules/es.regexp.constructor.js";
|
|
2
|
+
import "core-js/modules/es.regexp.dot-all.js";
|
|
3
|
+
import "core-js/modules/es.regexp.exec.js";
|
|
4
|
+
const JSON_PROTO = Object.getPrototypeOf({});
|
|
5
|
+
function defaultIsMergeableObjectFactory() {
|
|
6
|
+
return function (value) {
|
|
7
|
+
return typeof value === 'object' && value !== null && !(value instanceof RegExp) && !(value instanceof Date);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function deepmergeConstructor(options) {
|
|
11
|
+
function isNotPrototypeKey(value) {
|
|
12
|
+
return value !== 'constructor' && value !== 'prototype' && value !== '__proto__';
|
|
13
|
+
}
|
|
14
|
+
function cloneArray(value) {
|
|
15
|
+
let i = 0;
|
|
16
|
+
const il = value.length;
|
|
17
|
+
const result = new Array(il);
|
|
18
|
+
for (i; i < il; ++i) {
|
|
19
|
+
result[i] = clone(value[i]);
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
function cloneObject(target) {
|
|
24
|
+
const result = {};
|
|
25
|
+
if (cloneProtoObject && Object.getPrototypeOf(target) !== JSON_PROTO) {
|
|
26
|
+
return cloneProtoObject(target);
|
|
27
|
+
}
|
|
28
|
+
const targetKeys = getKeys(target);
|
|
29
|
+
let i;
|
|
30
|
+
let il;
|
|
31
|
+
let key;
|
|
32
|
+
for (i = 0, il = targetKeys.length; i < il; ++i) {
|
|
33
|
+
isNotPrototypeKey(key = targetKeys[i]) && (result[key] = clone(target[key]));
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
38
|
+
const getKeys = options !== null && options !== void 0 && options.symbols ? function (value) {
|
|
39
|
+
const result = Object.keys(value);
|
|
40
|
+
const keys = Object.getOwnPropertySymbols(value);
|
|
41
|
+
for (let i = 0, il = keys.length; i < il; ++i) {
|
|
42
|
+
propertyIsEnumerable.call(value, keys[i]) && result.push(keys[i]);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
} : value => Object.keys(value);
|
|
46
|
+
const cloneProtoObject = typeof (options === null || options === void 0 ? void 0 : options.cloneProtoObject) === 'function' ? options.cloneProtoObject : undefined;
|
|
47
|
+
const isMergeableObject = typeof (options === null || options === void 0 ? void 0 : options.isMergeableObject) === 'function' ? options.isMergeableObject : defaultIsMergeableObjectFactory();
|
|
48
|
+
const onlyDefinedProperties = (options === null || options === void 0 ? void 0 : options.onlyDefinedProperties) === true;
|
|
49
|
+
function isPrimitive(value) {
|
|
50
|
+
return typeof value !== 'object' || value === null;
|
|
51
|
+
}
|
|
52
|
+
const mergeArray = options && typeof options.mergeArray === 'function' ? options.mergeArray({
|
|
53
|
+
clone,
|
|
54
|
+
deepmerge: _deepmerge,
|
|
55
|
+
getKeys,
|
|
56
|
+
isMergeableObject
|
|
57
|
+
}) : function (target, source) {
|
|
58
|
+
const tl = target.length;
|
|
59
|
+
const sl = source.length;
|
|
60
|
+
let i = 0;
|
|
61
|
+
const result = new Array(tl + sl);
|
|
62
|
+
for (i; i < tl; ++i) {
|
|
63
|
+
result[i] = clone(target[i]);
|
|
64
|
+
}
|
|
65
|
+
for (i = 0; i < sl; ++i) {
|
|
66
|
+
result[i + tl] = clone(source[i]);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
function clone(entry) {
|
|
71
|
+
return isMergeableObject(entry) ? Array.isArray(entry) ? cloneArray(entry) : cloneObject(entry) : entry;
|
|
72
|
+
}
|
|
73
|
+
function mergeObject(target, source) {
|
|
74
|
+
const result = {};
|
|
75
|
+
const targetKeys = getKeys(target);
|
|
76
|
+
const sourceKeys = getKeys(source);
|
|
77
|
+
let i;
|
|
78
|
+
let il;
|
|
79
|
+
let key;
|
|
80
|
+
for (i = 0, il = targetKeys.length; i < il; ++i) {
|
|
81
|
+
isNotPrototypeKey(key = targetKeys[i]) && sourceKeys.indexOf(key) === -1 && (result[key] = clone(target[key]));
|
|
82
|
+
}
|
|
83
|
+
for (i = 0, il = sourceKeys.length; i < il; ++i) {
|
|
84
|
+
if (!isNotPrototypeKey(key = sourceKeys[i])) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (key in target) {
|
|
88
|
+
if (targetKeys.indexOf(key) !== -1) {
|
|
89
|
+
if (cloneProtoObject && isMergeableObject(source[key]) && Object.getPrototypeOf(source[key]) !== JSON_PROTO) {
|
|
90
|
+
result[key] = cloneProtoObject(source[key]);
|
|
91
|
+
} else {
|
|
92
|
+
result[key] = _deepmerge(target[key], source[key]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
if (onlyDefinedProperties && typeof source[key] === 'undefined') {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
result[key] = clone(source[key]);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function _deepmerge(target, source) {
|
|
105
|
+
if (onlyDefinedProperties && typeof source === 'undefined') {
|
|
106
|
+
return clone(target);
|
|
107
|
+
}
|
|
108
|
+
const sourceIsArray = Array.isArray(source);
|
|
109
|
+
const targetIsArray = Array.isArray(target);
|
|
110
|
+
if (isPrimitive(source)) {
|
|
111
|
+
return source;
|
|
112
|
+
}
|
|
113
|
+
if (!isMergeableObject(target)) {
|
|
114
|
+
return clone(source);
|
|
115
|
+
}
|
|
116
|
+
if (sourceIsArray && targetIsArray) {
|
|
117
|
+
return mergeArray(target, source);
|
|
118
|
+
}
|
|
119
|
+
if (sourceIsArray !== targetIsArray) {
|
|
120
|
+
return clone(source);
|
|
121
|
+
}
|
|
122
|
+
return mergeObject(target, source);
|
|
123
|
+
}
|
|
124
|
+
return options !== null && options !== void 0 && options.all ? function () {
|
|
125
|
+
switch (arguments.length) {
|
|
126
|
+
case 0:
|
|
127
|
+
return {};
|
|
128
|
+
case 1:
|
|
129
|
+
return clone(arguments.length <= 0 ? undefined : arguments[0]);
|
|
130
|
+
case 2:
|
|
131
|
+
return _deepmerge(arguments.length <= 0 ? undefined : arguments[0], arguments.length <= 1 ? undefined : arguments[1]);
|
|
132
|
+
}
|
|
133
|
+
let result = {};
|
|
134
|
+
for (let i = 0, il = arguments.length; i < il; ++i) {
|
|
135
|
+
result = _deepmerge(result, i < 0 || arguments.length <= i ? undefined : arguments[i]);
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
} : _deepmerge;
|
|
139
|
+
}
|
|
140
|
+
export const deepmerge = deepmergeConstructor();
|
|
141
|
+
export { defaultIsMergeableObjectFactory as isMergeableObject };
|
package/dist/chat/index.d.ts
CHANGED