@ray-js/t-agent 0.0.8 → 0.0.9-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 CHANGED
@@ -702,6 +702,12 @@ Hooks:
702
702
  - `extension` 扩展数据
703
703
  - `responseMessage` 响应消息
704
704
  - `result.messages` 消息列表
705
+ - `onTTTAction` tile 使用 `sendAction` 时触发
706
+ - `tile` 触发的 tile
707
+ - `action` TTTAction
708
+ - `onCardsReceived` 当收到卡片时触发
709
+ - `extension` 扩展数据
710
+ - `result.cards` 卡片列表
705
711
 
706
712
  ### withBuildIn 插件
707
713
 
@@ -1229,9 +1235,11 @@ import {
1229
1235
  } from '@ray-js/t-agent-ui-ray';
1230
1236
  import { View, Text, Button } from '@ray-js/ray';
1231
1237
 
1232
- function MyCard(props: { card: ChatCardObject }) {
1238
+ const MyCard: ChatCardComponent<{ title: string }, { clicked: boolean }> = props => {
1233
1239
  // 如果你需要拿到 agent、message、tile、emitEvent 等属性,可以使用 useTileProps
1234
1240
  const { message, agent, tile, emitEvent } = useTileProps();
1241
+ const { card, setCardState } = props;
1242
+ const { cardData, cardState, cardCode } = card as ChatCardObject<{ title: string }>;
1235
1243
 
1236
1244
  // 如果你需要发送一个 TTTAction,可以使用 useSendAction
1237
1245
  const sendAction = useSendAction();
@@ -1240,15 +1248,18 @@ function MyCard(props: { card: ChatCardObject }) {
1240
1248
  <View>
1241
1249
  <Text>My Card</Text>
1242
1250
  <Button
1243
- onClick={() =>
1244
- sendAction({ type: 'sendMessage', blocks: [{ type: 'text', text: 'hello' }] })
1245
- }
1251
+ onClick={() => {
1252
+ sendAction({ type: 'sendMessage', blocks: [{ type: 'text', text: 'hello' }] });
1253
+ // 如果需要更新卡片状态,可以使用 setCardState
1254
+ // 第二个参数表示是否持久化状态
1255
+ setCardState({ clicked: true }, { persist: true });
1256
+ }}
1246
1257
  >
1247
1258
  填充文本到输入框
1248
1259
  </Button>
1249
1260
  </View>
1250
1261
  );
1251
- }
1262
+ };
1252
1263
 
1253
1264
  const renderOptions = {
1254
1265
  ...defaultRenderOptions,
@@ -1388,3 +1399,4 @@ const renderOptions = {
1388
1399
  | t-agent.input.voice.require-permission | MessageInput 切换语音输入 | 需要授权录音权限 |
1389
1400
  | t-agent.input.upload.failed | MessageInput 上传文件 | 文件上传失败 |
1390
1401
  | t-agent.message.feedback.success | BubbleTile 消息评价 | 反馈成功 |
1402
+ | t-agent-bubble-tile-aborted | BubbleTile 消息 | 用户中断 |
package/README.md CHANGED
@@ -696,6 +696,12 @@ Hooks:
696
696
  - `extension`: Extension data
697
697
  - `responseMessage`: Response message
698
698
  - `result.messages`: Message list
699
+ - `onTTTAction` When using `sendAction` in the tile, this hook triggers.
700
+ - `tile` Tile object
701
+ - `action` TTTAction
702
+ - `onCardsReceived` When receiving cards, this hook triggers.
703
+ - `extension` Extension data
704
+ - `result.cards` Card list
699
705
 
700
706
  ### withBuildIn Plugin
701
707
 
@@ -1224,9 +1230,11 @@ import {
1224
1230
  } from '@ray-js/t-agent-ui-ray';
1225
1231
  import { View, Text, Button } from '@ray-js/ray';
1226
1232
 
1227
- function MyCard(props: { card: ChatCardObject }) {
1233
+ const MyCard: ChatCardComponent<{ title: string }, { clicked: boolean }> = props => {
1228
1234
  // If you need to access attributes like agent, message, tile, emitEvent, use useTileProps
1229
1235
  const { message, agent, tile, emitEvent } = useTileProps();
1236
+ const { card, setCardState } = props;
1237
+ const { cardData, cardState, cardCode } = card as ChatCardObject<{ title: string }>;
1230
1238
 
1231
1239
  // If you need to send a TTTAction, use useSendAction
1232
1240
  const sendAction = useSendAction();
@@ -1235,15 +1243,18 @@ function MyCard(props: { card: ChatCardObject }) {
1235
1243
  <View>
1236
1244
  <Text>My Card</Text>
1237
1245
  <Button
1238
- onClick={() =>
1239
- sendAction({ type: 'sendMessage', blocks: [{ type: 'text', text: 'hello' }] })
1240
- }
1246
+ onClick={() => {
1247
+ sendAction({ type: 'sendMessage', blocks: [{ type: 'text', text: 'hello' }] });
1248
+ // If you want to set the card state, use setCardState
1249
+ // The second parameter is used to determine whether to persist the card state, default is false
1250
+ setCardState({ clicked: true }, { persist: true });
1251
+ }}
1241
1252
  >
1242
1253
  Fill text into input
1243
1254
  </Button>
1244
1255
  </View>
1245
1256
  );
1246
- }
1257
+ };
1247
1258
 
1248
1259
  const renderOptions = {
1249
1260
  ...defaultRenderOptions,
@@ -1383,3 +1394,4 @@ Below are the built-in multilingual keys:
1383
1394
  | t-agent.input.voice.require-permission | MessageInput switch to voice input | Need to grant recording permission |
1384
1395
  | t-agent.input.upload.failed | MessageInput file upload | File upload failed |
1385
1396
  | t-agent.message.feedback.success | BubbleTile message feedback | Feedback successful |
1397
+ | t-agent-bubble-tile-aborted | BubbleTile message | User aborted |
@@ -213,8 +213,7 @@ export default class ChatAgent {
213
213
  await message.set({
214
214
  status: ChatMessageStatus.UPDATING
215
215
  }).bubble.setText(text).update();
216
- }
217
- if (part.type === 'attachment' && attachmentCompose) {
216
+ } else if (part.type === 'attachment' && attachmentCompose) {
218
217
  const list = (await attachmentCompose(message, part)) || [];
219
218
  for (const m of list) {
220
219
  m.set({
@@ -223,12 +222,23 @@ export default class ChatAgent {
223
222
  await m.show();
224
223
  messages.push(m);
225
224
  }
226
- }
227
- if (part.type === 'error') {
225
+ } else if (part.type === 'error') {
228
226
  if (!message.bubble.text) {
229
227
  message.bubble.setText(part.error.message);
230
228
  }
231
229
  await message.bubble.setStatus(part.level === 'error' ? BubbleTileStatus.ERROR : BubbleTileStatus.WARNING).setInfo(part.error.message).update();
230
+ } else if (part.type === 'abort') {
231
+ // 如果只有一条响应消息,则直接设置为中断状态
232
+ if (messages.length === 1) {
233
+ if (message.status === ChatMessageStatus.UPDATING) {
234
+ await message.bubble.setStatus(BubbleTileStatus.ABORTED).update();
235
+ } else {
236
+ await message.remove();
237
+ messages.pop();
238
+ }
239
+ }
240
+ // stop update
241
+ break;
232
242
  }
233
243
  }
234
244
  }
@@ -1,6 +1,8 @@
1
1
  import { MessagePart, StreamResponseInstance } from './types';
2
2
  export default class StreamResponse implements StreamResponseInstance {
3
3
  private partStream;
4
+ private reader;
5
+ private aborted;
4
6
  /**
5
7
  * Create a new StreamResponse instance.
6
8
  *
@@ -1,3 +1,4 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
1
2
  import _awaitAsyncGenerator from "@babel/runtime/helpers/esm/awaitAsyncGenerator";
2
3
  import _wrapAsyncGenerator from "@babel/runtime/helpers/esm/wrapAsyncGenerator";
3
4
  import "core-js/modules/es.symbol.async-iterator.js";
@@ -8,6 +9,8 @@ export default class StreamResponse {
8
9
  * @param partStream
9
10
  */
10
11
  constructor(partStream) {
12
+ _defineProperty(this, "reader", null);
13
+ _defineProperty(this, "aborted", false);
11
14
  this.partStream = partStream;
12
15
  }
13
16
 
@@ -15,16 +18,41 @@ export default class StreamResponse {
15
18
  * Get all parts of the response as an async iterator.
16
19
  */
17
20
  parts() {
21
+ if (this.reader) {
22
+ throw new Error('parts() can only be called once');
23
+ }
18
24
  const reader = this.partStream.getReader();
25
+ this.reader = reader;
26
+
27
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
28
+ const resp = this;
19
29
  return {
20
30
  [Symbol.asyncIterator]() {
21
31
  return _wrapAsyncGenerator(function* () {
22
32
  try {
23
33
  while (true) {
34
+ if (resp.aborted) {
35
+ yield {
36
+ type: 'abort',
37
+ level: 'warn',
38
+ error: new Error('User aborted'),
39
+ meta: {}
40
+ };
41
+ break;
42
+ }
24
43
  const {
25
44
  done,
26
45
  value
27
46
  } = yield _awaitAsyncGenerator(reader.read());
47
+ if (resp.aborted) {
48
+ yield {
49
+ type: 'abort',
50
+ level: 'warn',
51
+ error: new Error('User aborted'),
52
+ meta: {}
53
+ };
54
+ break;
55
+ }
28
56
  if (done) break;
29
57
  yield value;
30
58
  }
@@ -42,6 +70,10 @@ export default class StreamResponse {
42
70
  * @param reason
43
71
  */
44
72
  cancel(reason) {
45
- return this.partStream.cancel(reason);
73
+ this.aborted = true;
74
+ if (this.reader) {
75
+ return this.reader.cancel(reason);
76
+ }
77
+ throw new Error('cancel() can only be called after parts()');
46
78
  }
47
79
  }
@@ -3,10 +3,10 @@ import StreamResponse from './StreamResponse';
3
3
  import ChatTile from './ChatTile';
4
4
  import ChatBubbleTile from './ChatBubbleTile';
5
5
  import ChatMessage from './ChatMessage';
6
- import { generateId, safeParseJSON, sleep, generateInt, isAbortError, debounce, shuffleWithSeed } from './utils';
6
+ import { generateId, safeParseJSON, isAbortError, shuffleWithSeed } from './utils';
7
7
  import Logger, { getLogger } from './Logger';
8
8
  import { Emitter, EmitterEvent } from './Emitter';
9
9
  export { createHooks, Hookable } from 'hookable';
10
- export { ChatAgent, StreamResponse, ChatTile, ChatBubbleTile, ChatMessage, generateId, generateInt, safeParseJSON, getLogger, Logger, Emitter, EmitterEvent, isAbortError, sleep, debounce, shuffleWithSeed, };
10
+ export { ChatAgent, StreamResponse, ChatTile, ChatBubbleTile, ChatMessage, generateId, safeParseJSON, getLogger, Logger, Emitter, EmitterEvent, isAbortError, shuffleWithSeed, };
11
11
  export * from './createChatAgent';
12
12
  export * from './types';
@@ -3,10 +3,10 @@ import StreamResponse from './StreamResponse';
3
3
  import ChatTile from './ChatTile';
4
4
  import ChatBubbleTile from './ChatBubbleTile';
5
5
  import ChatMessage from './ChatMessage';
6
- import { generateId, safeParseJSON, sleep, generateInt, isAbortError, debounce, shuffleWithSeed } from './utils';
6
+ import { generateId, safeParseJSON, isAbortError, shuffleWithSeed } from './utils';
7
7
  import Logger, { getLogger } from './Logger';
8
8
  import { Emitter, EmitterEvent } from './Emitter';
9
9
  export { createHooks, Hookable } from 'hookable';
10
- export { ChatAgent, StreamResponse, ChatTile, ChatBubbleTile, ChatMessage, generateId, generateInt, safeParseJSON, getLogger, Logger, Emitter, EmitterEvent, isAbortError, sleep, debounce, shuffleWithSeed };
10
+ export { ChatAgent, StreamResponse, ChatTile, ChatBubbleTile, ChatMessage, generateId, safeParseJSON, getLogger, Logger, Emitter, EmitterEvent, isAbortError, shuffleWithSeed };
11
11
  export * from './createChatAgent';
12
12
  export * from './types';
@@ -97,7 +97,8 @@ export interface InputBlock {
97
97
  export declare enum BubbleTileStatus {
98
98
  NORMAL = "normal",
99
99
  WARNING = "warning",
100
- ERROR = "error"
100
+ ERROR = "error",
101
+ ABORTED = "aborted"
101
102
  }
102
103
  export interface AbortSignalObject {
103
104
  aborted: boolean;
@@ -143,7 +144,7 @@ export type ChatAgentPluginHandler = {
143
144
  export type ChatAgentPlugin<T extends ChatAgentPluginHandler = Record<string, any>> = (agent: ChatAgent) => T;
144
145
  export type AddHookCallback<H, T extends keyof H> = (fn: H[T], type?: 'before' | 'after' | undefined) => () => void;
145
146
  export interface ErrorPart {
146
- type: 'error';
147
+ type: 'error' | 'abort';
147
148
  level: 'error' | 'warn';
148
149
  error: Error;
149
150
  meta: Record<string, any>;
@@ -19,6 +19,7 @@ export let BubbleTileStatus = /*#__PURE__*/function (BubbleTileStatus) {
19
19
  BubbleTileStatus["NORMAL"] = "normal";
20
20
  BubbleTileStatus["WARNING"] = "warning";
21
21
  BubbleTileStatus["ERROR"] = "error";
22
+ BubbleTileStatus["ABORTED"] = "aborted";
22
23
  return BubbleTileStatus;
23
24
  }({});
24
25
  export let FinishReason = /*#__PURE__*/function (FinishReason) {
@@ -1,32 +1,6 @@
1
1
  export declare function generateId(length?: number): string;
2
- export declare function generateInt(min: number, max: number): number;
3
2
  export declare function deepCloneToPlainObject(obj: any): any;
4
3
  export declare function safeParseJSON<T = any>(str: any): T | undefined;
5
4
  export declare function deepMerge(target: any, source: any): any;
6
- export declare const sleep: (ms: number) => Promise<unknown>;
7
5
  export declare function isAbortError(reason: any): any;
8
- type AnyFunction = (...arguments_: readonly any[]) => unknown;
9
- /**
10
- * Creates a debounced function that delays execution until `wait` milliseconds have passed since its last invocation.
11
- *
12
- * Set the `immediate` option to `true` to execute the function immediately at the start of the `wait` interval, preventing issues such as double-clicks on a button.
13
- *
14
- * The returned function has the following methods:
15
- *
16
- * - `.isPending` indicates whether the debounce delay is currently active.
17
- * - `.clear()` cancels any scheduled executions.
18
- * - `.flush()` if an execution is scheduled then it will be immediately executed and the timer will be cleared.
19
- * - `.trigger()` executes the function immediately and clears the timer if it was previously set.
20
- */
21
- export declare function debounce<F extends AnyFunction>(function_: F, wait?: number, options?: {
22
- immediate?: boolean;
23
- }): DebouncedFunction<F>;
24
- interface DebouncedFunction<F extends AnyFunction> {
25
- (...arguments_: Parameters<F>): ReturnType<F> | undefined;
26
- readonly isPending: boolean;
27
- clear(): void;
28
- flush(): void;
29
- trigger(): void;
30
- }
31
6
  export declare function shuffleWithSeed<T>(array: T[], seed: string): T[];
32
- export {};
@@ -14,9 +14,6 @@ export function generateId() {
14
14
  }
15
15
  return result;
16
16
  }
17
- export function generateInt(min, max) {
18
- return Math.floor(Math.random() * (max - min + 1) + min);
19
- }
20
17
  export function deepCloneToPlainObject(obj) {
21
18
  // 判断是否是对象或数组
22
19
  if (obj === null || typeof obj !== 'object') {
@@ -83,101 +80,9 @@ export function deepMerge(target, source) {
83
80
  }
84
81
  return target;
85
82
  }
86
- export const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
87
83
  export function isAbortError(reason) {
88
84
  return reason && typeof Error !== 'undefined' && reason instanceof Error && reason.name === 'AbortError';
89
85
  }
90
- /**
91
- * Creates a debounced function that delays execution until `wait` milliseconds have passed since its last invocation.
92
- *
93
- * Set the `immediate` option to `true` to execute the function immediately at the start of the `wait` interval, preventing issues such as double-clicks on a button.
94
- *
95
- * The returned function has the following methods:
96
- *
97
- * - `.isPending` indicates whether the debounce delay is currently active.
98
- * - `.clear()` cancels any scheduled executions.
99
- * - `.flush()` if an execution is scheduled then it will be immediately executed and the timer will be cleared.
100
- * - `.trigger()` executes the function immediately and clears the timer if it was previously set.
101
- */
102
- export function debounce(function_) {
103
- let wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
104
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
105
- if (typeof function_ !== 'function') {
106
- throw new TypeError("Expected the first parameter to be a function, got `".concat(typeof function_, "`."));
107
- }
108
- if (wait < 0) {
109
- throw new RangeError('`wait` must not be negative.');
110
- }
111
- const {
112
- immediate = false
113
- } = options;
114
- let storedContext;
115
- let storedArguments;
116
- let timeoutId;
117
- let timestamp;
118
- let result;
119
- function run() {
120
- const callContext = storedContext;
121
- const callArguments = storedArguments;
122
- storedContext = undefined;
123
- storedArguments = undefined;
124
- result = function_.apply(callContext, callArguments);
125
- return result;
126
- }
127
- function later() {
128
- const last = Date.now() - timestamp;
129
- if (last < wait && last >= 0) {
130
- timeoutId = setTimeout(later, wait - last);
131
- } else {
132
- timeoutId = undefined;
133
- if (!immediate) {
134
- result = run();
135
- }
136
- }
137
- }
138
- const debounced = function () {
139
- if (storedContext && this !== storedContext && Object.getPrototypeOf(this) === Object.getPrototypeOf(storedContext)) {
140
- throw new Error('Debounced method called with different contexts of the same prototype.');
141
- }
142
- storedContext = this;
143
- for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) {
144
- arguments_[_key] = arguments[_key];
145
- }
146
- storedArguments = arguments_;
147
- timestamp = Date.now();
148
- const callNow = immediate && !timeoutId;
149
- if (!timeoutId) {
150
- timeoutId = setTimeout(later, wait);
151
- }
152
- if (callNow) {
153
- result = run();
154
- }
155
- return result;
156
- };
157
- Object.defineProperty(debounced, 'isPending', {
158
- get() {
159
- return timeoutId !== undefined;
160
- }
161
- });
162
- debounced.clear = () => {
163
- if (!timeoutId) {
164
- return;
165
- }
166
- clearTimeout(timeoutId);
167
- timeoutId = undefined;
168
- };
169
- debounced.flush = () => {
170
- if (!timeoutId) {
171
- return;
172
- }
173
- debounced.trigger();
174
- };
175
- debounced.trigger = () => {
176
- result = run();
177
- debounced.clear();
178
- };
179
- return debounced;
180
- }
181
86
  function seedRandom(seed) {
182
87
  let h = 0;
183
88
  // 将字符串种子转化为哈希值
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/t-agent",
3
- "version": "0.0.8",
3
+ "version": "0.0.9-beta-2",
4
4
  "author": "Tuya.inc",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -26,5 +26,5 @@
26
26
  "build": "ray build --type=component --output dist",
27
27
  "clean": "rimraf ./dist"
28
28
  },
29
- "gitHead": "686e9d17bd1a96074d3ac16ac2a3d73e1aa17f8f"
29
+ "gitHead": "45f4f153fe2ce1e218a74f9bd3df726cf4e06d63"
30
30
  }