@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.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 { ChatContainer, MessageInput, MessageList, MessageActionBar } from '@ray-js/t-agent-ui-ray';
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
- try {
67
- // The order of applying plugins matters
68
- const agent = createChatAgent(
69
- withUI(), // The withUI plugin provides default UI behavior, essential
70
- withAIStream({
71
- // Connects to the mini-program AI agent platform, essential in mini-program
72
- earlyStart: true, // Whether to establish connection during onAgentStart phase
73
- agentId: '', // Enter your agent ID
74
- }),
75
- withDebug(), // Enables logging to the console
76
- withBuildIn() // Provides built-in features
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
- // Lifecycle hooks for custom behavior registration
80
- const { onChatStart, createMessage, onChatResume, onError, onInputBlocksPush, session } = agent;
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
- // Initialize chat with a message
83
- onChatStart(async result => {
84
- const hello = createMessage({
85
- role: 'assistant',
86
- });
105
+ const { onChatStart, createMessage } = agent;
87
106
 
88
- hello.bubble.setText('Hello, world!');
89
- result.messages.push(hello);
90
- // Persist message for display upon next entry
91
- await hello.persist();
107
+ onChatStart(async result => {
108
+ const hello = createMessage({
109
+ role: 'assistant',
92
110
  });
93
111
 
94
- // Message upon chat resume
95
- onChatResume(async result => {
96
- const welcomeBack = createMessage({
97
- role: 'assistant',
98
- });
112
+ hello.bubble.setText('Hello, world!');
113
+ result.messages.push(hello);
114
+ await hello.persist();
115
+ });
99
116
 
100
- welcomeBack.bubble.setText('Welcome back');
101
- result.messages.push(welcomeBack);
102
- await welcomeBack.persist();
103
- });
104
- return agent;
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` Skill data array (ReceivedTextSkillPacketBody[])
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
+ ![mcp-config.jpg](https://static1.tuyacn.com/static/txp-ray-TAgent/mcp-config.jpg)
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
+ ![custom-var-config.jpg](https://static1.tuyacn.com/static/txp-ray-TAgent/custom-var-config.jpg)
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.sessionAttributes = {
838
- 'custom.param': {
839
- userName: { value: 'John' },
840
- userLevel: { value: 'Plus' },
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 each time a message is sent
955
+ // Pass dynamic context every time a message is sent
846
956
  if (type === 'start-event') {
847
- result.eventAttributes = {
848
- 'custom.param': {
849
- timestamp: { value: Date.now() },
850
- pid: { value: '123456' },
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<any>[];
33
- fallback?: import("./types").TipTileData | undefined;
32
+ children: import("./types").ChatTileObject[];
33
+ fallback?: import("./types").TipTileData;
34
34
  };
35
35
  }
@@ -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, deepMerge, generateId } from './utils';
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
- console.warn('message is already show');
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
- console.warn('message is not show');
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
- console.warn('message is not show');
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 = deepMerge(this.meta, 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 | undefined) => any;
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['onChange']) => () => void;
25
+ onChange: (fn: ChatSessionHooks["onChange"]) => () => void;
26
26
  getLatestMessage: () => ChatMessage | undefined;
27
27
  dispose: () => Promise<void>;
28
28
  }
@@ -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 };
@@ -12,3 +12,4 @@ export { ChatAgent, ChatSession, StreamResponse, ChatTile, ChatBubbleTile, ChatM
12
12
  export * from './createChatAgent';
13
13
  export * from './types';
14
14
  export * from './json';
15
+ export * from './deepmerge';