@opentiny/next-sdk 0.2.1 → 0.2.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.
@@ -44,12 +44,18 @@ export class AgentModelProvider {
44
44
  onUpdatedTools: (() => void) | undefined
45
45
  /** Agent 内部报错时,抛出的错误事件 */
46
46
  onError: ((msg: string, err?: any) => void) | undefined
47
- /** MCP Client 断开连接时的回调 */
48
- onClientDisconnected?: (serverName: string, reason?: string) => void
49
47
  /** 缓存 ai-sdk response 中的 多轮会话的上下文 */
50
- messages: any[] = []
48
+ responseMessages: any[] = []
51
49
  /** 是否使用 ReAct 模式(通过提示词而非 function calling 进行工具调用) */
52
50
  useReActMode: boolean = false
51
+ /** 流结束后,返回token细节的事件 */
52
+ onUsage?: (usage: {
53
+ cachedInputTokens: number
54
+ inputTokens: number
55
+ reasoningTokens: number
56
+ outputTokens: number
57
+ totalTokens: number
58
+ }) => void
53
59
 
54
60
  constructor({ llmConfig, mcpServers }: IAgentModelProviderOption) {
55
61
  if (!llmConfig) {
@@ -362,7 +368,7 @@ export class AgentModelProvider {
362
368
  } else if (options.messages) {
363
369
  currentMessages = [...options.messages]
364
370
  } else {
365
- currentMessages = [...this.messages]
371
+ currentMessages = [...this.responseMessages]
366
372
  }
367
373
 
368
374
  // 确保 model 是字符串类型(ReAct 模式下 model 应该是模型名称字符串)
@@ -436,7 +442,7 @@ export class AgentModelProvider {
436
442
  }
437
443
 
438
444
  /**
439
- * 构建用于模型调用的消息列表(magentic-ui 风格)
445
+ * 构建用于模型调用的消息列表
440
446
  * 策略:保留所有文本消息,仅限制图片数量(类似 magentic-ui 的 maybe_remove_old_screenshots)
441
447
  *
442
448
  * @param systemMessage 系统提示词
@@ -502,17 +508,16 @@ export class AgentModelProvider {
502
508
  const allUserMessages = systemMessage ? messages.slice(1) : messages
503
509
 
504
510
  let stepCount = 0
505
- // 配置:最多保留的图片数量(默认3张,类似 magentic-ui)
511
+ // 配置:最多保留的图片数量
506
512
  const maxImages = (options as any).maxImages ?? 3
507
513
 
508
514
  while (stepCount < maxSteps) {
509
515
  stepCount++
510
516
 
511
- // 构建用于模型调用的消息列表(magentic-ui 风格:保留所有文本,限制图片)
517
+ // 构建用于模型调用的消息列表
512
518
  const messagesForModel = this._buildMessagesForModel(systemMessage, allUserMessages, maxImages)
513
519
 
514
520
  // 调用 LLM(ReAct 模式下不传递 tools,因为工具调用通过提示词实现)
515
- // 参考 magentic-ui:保留所有文本历史(上下文完整),仅限制图片数量(优化 token)
516
521
  const { tools: _, ...restOptions } = options
517
522
  const result = await generateText({
518
523
  // @ts-ignore ProviderV2 是所有llm的父类,在每一个具体的llm类都有一个选择model的函数用法
@@ -532,7 +537,7 @@ export class AgentModelProvider {
532
537
 
533
538
  if (!action) {
534
539
  // 没有工具调用,返回最终结果
535
- this.messages = fullMessageHistory
540
+ this.responseMessages = fullMessageHistory
536
541
  return {
537
542
  text: assistantMessage,
538
543
  response: { messages: fullMessageHistory }
@@ -556,7 +561,7 @@ export class AgentModelProvider {
556
561
  }
557
562
 
558
563
  // 达到最大步数,返回最后一条消息
559
- this.messages = fullMessageHistory
564
+ this.responseMessages = fullMessageHistory
560
565
  const lastMessage = fullMessageHistory[fullMessageHistory.length - 2]?.content || ''
561
566
  return {
562
567
  text: lastMessage,
@@ -591,14 +596,14 @@ export class AgentModelProvider {
591
596
 
592
597
  let stepCount = 0
593
598
  let accumulatedText = ''
594
- // 配置:最多保留的图片数量(默认3张,类似 magentic-ui)
599
+ // 配置:最多保留的图片数量
595
600
  const maxImages = (options as any).maxImages ?? 3
596
601
 
597
602
  try {
598
603
  while (stepCount < maxSteps) {
599
604
  stepCount++
600
605
 
601
- // 构建用于模型调用的消息列表(magentic-ui 风格:保留所有文本,限制图片)
606
+ // 构建用于模型调用的消息列表
602
607
  const messagesForModel = self._buildMessagesForModel(systemMessage, allUserMessages, maxImages)
603
608
 
604
609
  // 移除 tools 选项,ReAct 模式下不传递 tools
@@ -646,7 +651,7 @@ export class AgentModelProvider {
646
651
  // 没有工具调用,结束流
647
652
  controller.enqueue({ type: 'text-end' })
648
653
  controller.close()
649
- self.messages = fullMessageHistory
654
+ self.responseMessages = fullMessageHistory
650
655
  // 触发 onFinish 回调
651
656
  streamCompleteResolver({ messages: fullMessageHistory })
652
657
  return
@@ -657,7 +662,7 @@ export class AgentModelProvider {
657
662
  // 视为对话结束
658
663
  controller.enqueue({ type: 'text-end' })
659
664
  controller.close()
660
- self.messages = fullMessageHistory
665
+ self.responseMessages = fullMessageHistory
661
666
  streamCompleteResolver({ messages: fullMessageHistory })
662
667
  return
663
668
  }
@@ -753,7 +758,7 @@ export class AgentModelProvider {
753
758
  // 达到最大步数
754
759
  controller.enqueue({ type: 'text-end' })
755
760
  controller.close()
756
- self.messages = fullMessageHistory
761
+ self.responseMessages = fullMessageHistory
757
762
  // 触发 onFinish 回调
758
763
  streamCompleteResolver({ messages: fullMessageHistory })
759
764
  } catch (error: any) {
@@ -795,16 +800,39 @@ export class AgentModelProvider {
795
800
  tools: this._tempMergeTools(options.tools) as ToolSet
796
801
  }
797
802
 
803
+ // 保存最后一条 user 消息,用于后续缓存
804
+ let lastUserMessage: any = null
805
+
798
806
  if (options.message && !options.messages) {
799
- this.messages.push({ role: 'user', content: options.message })
800
- chatOptions.messages = [...this.messages]
807
+ // 使用 options.message 创建 user 消息
808
+ lastUserMessage = { role: 'user', content: options.message }
809
+ this.responseMessages.push(lastUserMessage)
810
+ chatOptions.messages = [...this.responseMessages]
811
+ } else if (options.messages && options.messages.length > 0) {
812
+ // 从 options.messages 中获取最后一条 user 消息
813
+ const lastMessage = options.messages[options.messages.length - 1]
814
+ if (lastMessage.role === 'user') {
815
+ lastUserMessage = lastMessage
816
+ }
801
817
  }
802
818
 
803
819
  const result = chatMethod(chatOptions)
804
820
 
805
- // 缓存 ai-sdk的多轮对话的消息
821
+ // 缓存 ai-sdk 的多轮对话的消息
806
822
  ;(result as StreamTextResult<ToolSet, unknown>)?.response?.then((res: any) => {
807
- this.messages.push(...res.messages)
823
+ // 检查 res.messages 的第一条消息是否是 user 消息
824
+ // 如果不是,且有 lastUserMessage,则先添加 lastUserMessage
825
+ const firstMessage = res.messages?.[0]
826
+ if (lastUserMessage && firstMessage?.role !== 'user') {
827
+ this.responseMessages.push(lastUserMessage)
828
+ }
829
+ // 然后添加 AI 返回的消息
830
+ this.responseMessages.push(...res.messages)
831
+ })
832
+
833
+ // 读取使用量
834
+ result?.usage?.then((usage: any) => {
835
+ this.onUsage?.(usage)
808
836
  })
809
837
 
810
838
  return result
@@ -28,12 +28,18 @@ export declare class AgentModelProvider {
28
28
  onUpdatedTools: (() => void) | undefined;
29
29
  /** Agent 内部报错时,抛出的错误事件 */
30
30
  onError: ((msg: string, err?: any) => void) | undefined;
31
- /** MCP Client 断开连接时的回调 */
32
- onClientDisconnected?: (serverName: string, reason?: string) => void;
33
31
  /** 缓存 ai-sdk response 中的 多轮会话的上下文 */
34
- messages: any[];
32
+ responseMessages: any[];
35
33
  /** 是否使用 ReAct 模式(通过提示词而非 function calling 进行工具调用) */
36
34
  useReActMode: boolean;
35
+ /** 流结束后,返回token细节的事件 */
36
+ onUsage?: (usage: {
37
+ cachedInputTokens: number;
38
+ inputTokens: number;
39
+ reasoningTokens: number;
40
+ outputTokens: number;
41
+ totalTokens: number;
42
+ }) => void;
37
43
  constructor({ llmConfig, mcpServers }: IAgentModelProviderOption);
38
44
  /** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
39
45
  private _createOneClient;
@@ -76,7 +82,7 @@ export declare class AgentModelProvider {
76
82
  */
77
83
  private _removeImageFromMessage;
78
84
  /**
79
- * 构建用于模型调用的消息列表(magentic-ui 风格)
85
+ * 构建用于模型调用的消息列表
80
86
  * 策略:保留所有文本消息,仅限制图片数量(类似 magentic-ui 的 maybe_remove_old_screenshots)
81
87
  *
82
88
  * @param systemMessage 系统提示词
@@ -19171,7 +19171,9 @@ class Client extends Protocol {
19171
19171
  }
19172
19172
  return taskValidationResult.data;
19173
19173
  }
19174
- const validationResult = safeParse(CreateMessageResultSchema, result);
19174
+ const hasTools = params.tools || params.toolChoice;
19175
+ const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
19176
+ const validationResult = safeParse(resultSchema, result);
19175
19177
  if (!validationResult.success) {
19176
19178
  const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
19177
19179
  throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
@@ -26969,6 +26971,7 @@ const qrCode = "data:image/svg+xml,%3csvg%20viewBox='0%200%2040%2040'%20xmlns='h
26969
26971
  const iconCopy = "data:image/svg+xml,%3csvg%20viewBox='0%200%2012%2012'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20width='12.000000'%20height='12.000000'%20fill='none'%3e%3cdefs%3e%3cfilter%20id='pixso_custom_mask_type_luminance'%3e%3cfeColorMatrix%20type='matrix'%20values='1%200%200%200%200%200%201%200%200%200%200%200%201%200%200%200%200%200%201%200%20'%20/%3e%3c/filter%3e%3c/defs%3e%3cmask%20id='mask_0'%20width='11.999876'%20height='11.999876'%20x='0.000000'%20y='0.000000'%20maskUnits='userSpaceOnUse'%3e%3cg%20filter='url(%23pixso_custom_mask_type_luminance)'%3e%3cg%20id='mask401_19830'%3e%3cpath%20id='蒙版'%20d='M0%200L11.9999%200L11.9999%2011.9999L0%2011.9999L0%200ZM2.69992%201.34999L8.09977%201.34999C9.5082%201.34999%2010.6498%202.49167%2010.6498%203.89998L10.6498%209.2999C10.6498%2010.7082%209.5082%2011.8499%208.09977%2011.8499L2.69992%2011.8499C1.29149%2011.8499%200.149901%2010.7082%200.149901%209.2999L0.149901%203.89998C0.149901%202.49167%201.29149%201.34999%202.69992%201.34999Z'%20fill='rgb(196,196,196)'%20fill-rule='evenodd'%20/%3e%3c/g%3e%3c/g%3e%3c/mask%3e%3crect%20id='ic_public_copy'%20width='12.000000'%20height='12.000000'%20x='0.000000'%20y='0.000000'%20/%3e%3crect%20id='ic_public_copy-复制/base/ic_public_copy'%20width='11.999876'%20height='11.999876'%20x='0.000000'%20y='0.000000'%20fill='rgb(255,255,255)'%20fill-opacity='0'%20/%3e%3cpath%20id='path1'%20d='M0.000134537%205.99497C0.000134537%205.05748%20-0.00236544%204.11999%200.000134537%203.1825C-0.00236544%202.72751%200.055134%202.27501%200.165133%201.83752C0.41263%200.907526%201.01762%200.355032%201.94761%200.140034C2.41261%200.040035%202.8901%20-0.00746449%203.3651%203.54269e-05C5.16258%203.54269e-05%206.96006%203.54269e-05%208.76004%203.54269e-05C9.21254%20-0.00246455%209.66503%200.0475349%2010.1075%200.155034C11.065%200.387531%2011.64%200.995025%2011.8575%201.95002C11.9575%202.40001%2012.005%202.86001%2011.9975%203.3225C11.9975%205.13998%2011.9975%206.95746%2011.9975%208.77244C12%209.22244%2011.95%209.67243%2011.845%2010.1099C11.61%2011.0674%2011%2011.6374%2010.0475%2011.8574C9.58003%2011.9574%209.10504%2012.0049%208.62754%2011.9974C6.83756%2011.9974%205.04758%2011.9974%203.2576%2011.9974C2.80011%2012.0024%202.34511%2011.9499%201.90011%2011.8449C0.937625%2011.6124%200.360131%2011.0024%200.142633%2010.0424C0.0301342%209.55494%200.000134537%209.06744%200.000134537%208.57495C0.000134537%207.71495%200.000134537%206.85496%200.000134537%205.99497Z'%20fill='rgb(255,255,255)'%20fill-opacity='0'%20fill-rule='evenodd'%20/%3e%3ccircle%20id='path2'%20cx='5.99993801'%20cy='5.99993801'%20r='5.99993801'%20fill='rgb(255,255,255)'%20fill-opacity='0'%20/%3e%3cg%20id='mask'%20mask='url(%23mask_0)'%3e%3cg%20id='组合%208'%3e%3cpath%20id='path'%20d='M11.1%203.89993L11.1%206.8999C11.1%208.55488%209.75502%209.89737%208.10004%209.89737L5.10007%209.89737C3.44258%209.89737%202.1001%208.55488%202.1001%206.8999L2.1001%203.89993C2.1001%202.24245%203.44258%200.897461%205.10007%200.897461L8.10004%200.897461C9.75502%200.897461%2011.1%202.24245%2011.1%203.89993Z'%20fill-rule='nonzero'%20stroke='rgb(25,25,25)'%20stroke-linejoin='round'%20stroke-width='0.749992251'%20/%3e%3c/g%3e%3c/g%3e%3cpath%20id='path4'%20d='M2.10008%202.39746L8.10002%202.39746C8.92751%202.39746%209.6%203.06995%209.6%203.89995L9.6%209.89738C9.6%2010.7274%208.92751%2011.3999%208.10002%2011.3999L2.10008%2011.3999C1.27009%2011.3999%200.600098%2010.7274%200.600098%209.89738L0.600098%203.89995C0.600098%203.06995%201.27009%202.39746%202.10008%202.39746Z'%20fill='rgb(255,255,255)'%20fill-opacity='0'%20fill-rule='evenodd'%20/%3e%3cpath%20id='path4'%20d='M9.6%203.89995L9.6%209.89738C9.6%2010.7274%208.92751%2011.3999%208.10002%2011.3999L2.10008%2011.3999C1.27009%2011.3999%200.600098%2010.7274%200.600098%209.89738L0.600098%203.89995C0.600098%203.06995%201.27009%202.39746%202.10008%202.39746L8.10002%202.39746C8.92751%202.39746%209.6%203.06995%209.6%203.89995Z'%20fill-rule='nonzero'%20stroke='rgb(25,25,25)'%20stroke-linejoin='round'%20stroke-width='0.749992251'%20/%3e%3c/svg%3e";
26970
26972
  const DEFAULT_REMOTE_URL = "https://agent.opentiny.design/tiny-robot";
26971
26973
  const DEFAULT_QR_CODE_URL = "https://ai.opentiny.design/next-remoter";
26974
+ const DEFAULT_LOGO_URL = "https://ai.opentiny.design/next-remoter/svgs/logo-next-no-bg-left.svg";
26972
26975
  const getDefaultMenuItems = (options) => {
26973
26976
  return [
26974
26977
  {
@@ -27009,6 +27012,7 @@ const getDefaultMenuItems = (options) => {
27009
27012
  class FloatingBlock {
27010
27013
  constructor(options) {
27011
27014
  this.isExpanded = false;
27015
+ this.closingTimer = 0;
27012
27016
  this.getImageUrl = (asset) => {
27013
27017
  if (!asset) return;
27014
27018
  const img = new Image();
@@ -27016,15 +27020,13 @@ class FloatingBlock {
27016
27020
  return img;
27017
27021
  };
27018
27022
  this.renderItem = () => {
27019
- this.menuItems.filter((item) => item.show !== false).map(
27020
- (item) => {
27021
- const wrapper = document.getElementById(`tiny-remoter-icon-item-${item.action}`);
27022
- if (!wrapper) return;
27023
- wrapper.innerHTML = "";
27024
- const img = this.getImageUrl(item.icon);
27025
- if (img) wrapper.appendChild(img);
27026
- }
27027
- );
27023
+ this.menuItems.filter((item) => item.show !== false).map((item) => {
27024
+ const wrapper = document.getElementById(`tiny-remoter-icon-item-${item.action}`);
27025
+ if (!wrapper) return;
27026
+ wrapper.innerHTML = "";
27027
+ const img = this.getImageUrl(item.icon);
27028
+ if (img) wrapper.appendChild(img);
27029
+ });
27028
27030
  };
27029
27031
  this.readyTips = (el) => {
27030
27032
  const element = document.getElementById(el);
@@ -27043,9 +27045,14 @@ class FloatingBlock {
27043
27045
  this.options = {
27044
27046
  ...options,
27045
27047
  qrCodeUrl: options.qrCodeUrl || DEFAULT_QR_CODE_URL,
27046
- remoteUrl: options.remoteUrl || DEFAULT_REMOTE_URL
27048
+ remoteUrl: options.remoteUrl || DEFAULT_REMOTE_URL,
27049
+ logoUrl: options.logoUrl || DEFAULT_LOGO_URL
27047
27050
  };
27048
- this.menuItems = this.mergeMenuItems(options.menuItems);
27051
+ if (options.menuItems && options.menuItems.length === 0) {
27052
+ this.menuItems = [];
27053
+ } else {
27054
+ this.menuItems = this.mergeMenuItems(options.menuItems);
27055
+ }
27049
27056
  this.init();
27050
27057
  }
27051
27058
  // 计算 sessionPrefix 属性
@@ -27086,7 +27093,7 @@ class FloatingBlock {
27086
27093
  this.floatingBlock.className = "tiny-remoter-floating-block";
27087
27094
  this.floatingBlock.innerHTML = `
27088
27095
  <div class="tiny-remoter-floating-block__icon">
27089
- <img style="display: block; width: 56px;" src="${DEFAULT_QR_CODE_URL}/svgs/logo-next-no-bg-left.svg" alt="icon" />
27096
+ <img style="display: block; width: 56px;" src="${this.options.logoUrl}" alt="icon" />
27090
27097
  </div>
27091
27098
  `;
27092
27099
  document.body.appendChild(this.floatingBlock);
@@ -27124,7 +27131,26 @@ class FloatingBlock {
27124
27131
  }
27125
27132
  bindEvents() {
27126
27133
  this.floatingBlock.addEventListener("click", () => {
27127
- this.toggleDropdown();
27134
+ this.showAIChat();
27135
+ });
27136
+ this.floatingBlock.addEventListener("mouseenter", () => {
27137
+ this.openDropdown();
27138
+ if (this.closingTimer) {
27139
+ window.clearTimeout(this.closingTimer);
27140
+ this.closingTimer = 0;
27141
+ }
27142
+ });
27143
+ this.floatingBlock.addEventListener("mouseleave", () => {
27144
+ this.shouldCloseDropdown();
27145
+ });
27146
+ this.dropdownMenu.addEventListener("mouseenter", (e) => {
27147
+ if (this.closingTimer) {
27148
+ window.clearTimeout(this.closingTimer);
27149
+ this.closingTimer = 0;
27150
+ }
27151
+ });
27152
+ this.dropdownMenu.addEventListener("mouseleave", (e) => {
27153
+ this.shouldCloseDropdown();
27128
27154
  });
27129
27155
  this.dropdownMenu.addEventListener("click", (e) => {
27130
27156
  const target = e.target;
@@ -27155,18 +27181,20 @@ class FloatingBlock {
27155
27181
  }
27156
27182
  });
27157
27183
  }
27158
- toggleDropdown() {
27159
- if (this.isExpanded) {
27160
- this.closeDropdown();
27161
- } else {
27162
- this.openDropdown();
27163
- }
27164
- }
27165
27184
  openDropdown() {
27185
+ if (!this.menuItems || this.menuItems && this.menuItems.length === 0) {
27186
+ return;
27187
+ }
27166
27188
  this.isExpanded = true;
27167
27189
  this.floatingBlock.classList.add("expanded");
27168
27190
  this.dropdownMenu.classList.add("show");
27169
27191
  }
27192
+ shouldCloseDropdown() {
27193
+ this.closingTimer = window.setTimeout(() => {
27194
+ this.closeDropdown();
27195
+ }, 300);
27196
+ }
27197
+ /** 真正的立即关闭 */
27170
27198
  closeDropdown() {
27171
27199
  this.isExpanded = false;
27172
27200
  this.floatingBlock.classList.remove("expanded");
@@ -46144,7 +46172,7 @@ class AgentModelProvider {
46144
46172
  this.mcpClients = {};
46145
46173
  this.mcpTools = {};
46146
46174
  this.ignoreToolnames = [];
46147
- this.messages = [];
46175
+ this.responseMessages = [];
46148
46176
  this.useReActMode = false;
46149
46177
  if (!llmConfig) {
46150
46178
  throw new Error("llmConfig is required to initialize AgentModelProvider");
@@ -46386,7 +46414,7 @@ ${toolsPrompt}`;
46386
46414
  } else if (options.messages) {
46387
46415
  currentMessages = [...options.messages];
46388
46416
  } else {
46389
- currentMessages = [...this.messages];
46417
+ currentMessages = [...this.responseMessages];
46390
46418
  }
46391
46419
  const modelName = typeof model === "string" ? model : model?.modelId || "default-model";
46392
46420
  const systemPrompt = this._generateReActSystemPrompt(allTools, modelName, options.system);
@@ -46433,7 +46461,7 @@ ${toolsPrompt}`;
46433
46461
  };
46434
46462
  }
46435
46463
  /**
46436
- * 构建用于模型调用的消息列表(magentic-ui 风格)
46464
+ * 构建用于模型调用的消息列表
46437
46465
  * 策略:保留所有文本消息,仅限制图片数量(类似 magentic-ui 的 maybe_remove_old_screenshots)
46438
46466
  *
46439
46467
  * @param systemMessage 系统提示词
@@ -46491,7 +46519,7 @@ ${toolsPrompt}`;
46491
46519
  fullMessageHistory.push(assistantMsg);
46492
46520
  const action = parseReActAction(assistantMessage, tools);
46493
46521
  if (!action) {
46494
- this.messages = fullMessageHistory;
46522
+ this.responseMessages = fullMessageHistory;
46495
46523
  return {
46496
46524
  text: assistantMessage,
46497
46525
  response: { messages: fullMessageHistory }
@@ -46509,7 +46537,7 @@ ${resultString}
46509
46537
  allUserMessages.push(observationMessage);
46510
46538
  fullMessageHistory.push(observationMessage);
46511
46539
  }
46512
- this.messages = fullMessageHistory;
46540
+ this.responseMessages = fullMessageHistory;
46513
46541
  const lastMessage = fullMessageHistory[fullMessageHistory.length - 2]?.content || "";
46514
46542
  return {
46515
46543
  text: lastMessage,
@@ -46569,14 +46597,14 @@ ${resultString}
46569
46597
  if (!action) {
46570
46598
  controller.enqueue({ type: "text-end" });
46571
46599
  controller.close();
46572
- self2.messages = fullMessageHistory;
46600
+ self2.responseMessages = fullMessageHistory;
46573
46601
  streamCompleteResolver({ messages: fullMessageHistory });
46574
46602
  return;
46575
46603
  }
46576
46604
  if (action.toolName === "computer" && action.arguments?.action === "terminate") {
46577
46605
  controller.enqueue({ type: "text-end" });
46578
46606
  controller.close();
46579
- self2.messages = fullMessageHistory;
46607
+ self2.responseMessages = fullMessageHistory;
46580
46608
  streamCompleteResolver({ messages: fullMessageHistory });
46581
46609
  return;
46582
46610
  }
@@ -46638,7 +46666,7 @@ ${observationText}
46638
46666
  }
46639
46667
  controller.enqueue({ type: "text-end" });
46640
46668
  controller.close();
46641
- self2.messages = fullMessageHistory;
46669
+ self2.responseMessages = fullMessageHistory;
46642
46670
  streamCompleteResolver({ messages: fullMessageHistory });
46643
46671
  } catch (error) {
46644
46672
  controller.error(error);
@@ -46666,13 +46694,27 @@ ${observationText}
46666
46694
  ...options,
46667
46695
  tools: this._tempMergeTools(options.tools)
46668
46696
  };
46697
+ let lastUserMessage = null;
46669
46698
  if (options.message && !options.messages) {
46670
- this.messages.push({ role: "user", content: options.message });
46671
- chatOptions.messages = [...this.messages];
46699
+ lastUserMessage = { role: "user", content: options.message };
46700
+ this.responseMessages.push(lastUserMessage);
46701
+ chatOptions.messages = [...this.responseMessages];
46702
+ } else if (options.messages && options.messages.length > 0) {
46703
+ const lastMessage = options.messages[options.messages.length - 1];
46704
+ if (lastMessage.role === "user") {
46705
+ lastUserMessage = lastMessage;
46706
+ }
46672
46707
  }
46673
46708
  const result = chatMethod(chatOptions);
46674
46709
  result?.response?.then((res) => {
46675
- this.messages.push(...res.messages);
46710
+ const firstMessage = res.messages?.[0];
46711
+ if (lastUserMessage && firstMessage?.role !== "user") {
46712
+ this.responseMessages.push(lastUserMessage);
46713
+ }
46714
+ this.responseMessages.push(...res.messages);
46715
+ });
46716
+ result?.usage?.then((usage) => {
46717
+ this.onUsage?.(usage);
46676
46718
  });
46677
46719
  return result;
46678
46720
  }