From 47852f8f437b15b79aad2f95b830292131d773cf Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 11:36:31 +0300 Subject: [PATCH 1/9] Chat: add the ToolCall types, the toolCalls field of TextMessage and the renderToolsInMessageTemplate option --- packages/devextreme/js/ui/chat.d.ts | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/packages/devextreme/js/ui/chat.d.ts b/packages/devextreme/js/ui/chat.d.ts index 8f206c47dd45..b09500aca2a3 100644 --- a/packages/devextreme/js/ui/chat.d.ts +++ b/packages/devextreme/js/ui/chat.d.ts @@ -249,6 +249,48 @@ export type Attachment = { [key: string]: any; }; +/** + * @docid + * @namespace DevExpress.ui.dxChat + * @public + */ +export type ToolCallStatus = 'success' | 'error'; + +/** + * @docid + * @namespace DevExpress.ui.dxChat + * @public + */ +export type ToolCall = { + /** + * @docid + * @public + */ + name: string; + /** + * @docid + * @public + */ + arguments?: Record; + /** + * @docid + * @public + */ + result?: string | object; + /** + * @docid + * @public + */ + status?: ToolCallStatus; + /** + * @docid + * @public + */ + expanded?: boolean; + + [key: string]: any; +}; + /** * @docid * @namespace DevExpress.ui.dxChat @@ -315,6 +357,12 @@ export type TextMessage = MessageBase & { * @public */ isEdited?: boolean; + /** + * @docid + * @public + * @type Array + */ + toolCalls?: ToolCall[]; [key: string]: any; }; @@ -497,6 +545,12 @@ export interface dxChatOptions extends WidgetOptions { * @public */ reloadOnChange?: boolean; + /** + * @docid + * @default false + * @public + */ + renderToolsInMessageTemplate?: boolean; /** * @docid * @public From 71ff3fe20afb4034651e5b2ab0823404862339d7 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 11:37:39 +0300 Subject: [PATCH 2/9] Chat: update the generated d.ts bundle and the reexports --- packages/devextreme/js/ui/chat_types.d.ts | 2 ++ packages/devextreme/ts/dx.all.d.ts | 39 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/packages/devextreme/js/ui/chat_types.d.ts b/packages/devextreme/js/ui/chat_types.d.ts index 08de8b85118a..13c0b065323c 100644 --- a/packages/devextreme/js/ui/chat_types.d.ts +++ b/packages/devextreme/js/ui/chat_types.d.ts @@ -17,6 +17,8 @@ export { User, Alert, Attachment, + ToolCallStatus, + ToolCall, MessageType, TextMessage, ImageMessage, diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index 216a151e157b..cc31a48dc825 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -11860,6 +11860,10 @@ declare module DevExpress.ui { * [descr:dxChatOptions.reloadOnChange] */ reloadOnChange?: boolean; + /** + * [descr:dxChatOptions.renderToolsInMessageTemplate] + */ + renderToolsInMessageTemplate?: boolean; /** * [descr:dxChatOptions.sendButtonOptions] */ @@ -35000,9 +35004,44 @@ declare module DevExpress.ui.dxChat { * [descr:TextMessage.isEdited] */ isEdited?: boolean; + /** + * [descr:TextMessage.toolCalls] + */ + toolCalls?: ToolCall[]; [key: string]: any; }; + /** + * [descr:ToolCall] + */ + export type ToolCall = { + /** + * [descr:ToolCall.name] + */ + name: string; + /** + * [descr:ToolCall.arguments] + */ + arguments?: Record; + /** + * [descr:ToolCall.result] + */ + result?: string | object; + /** + * [descr:ToolCall.status] + */ + status?: ToolCallStatus; + /** + * [descr:ToolCall.expanded] + */ + expanded?: boolean; + + [key: string]: any; + }; + /** + * [descr:ToolCallStatus] + */ + export type ToolCallStatus = 'success' | 'error'; /** * [descr:User] */ From eacf34b5582ba11138053e4f0fa028a6dfa8811c Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 11:40:01 +0300 Subject: [PATCH 3/9] Angular: add toolCalls to the chat items --- .../src/core/tokens/index.ts | 1 + .../devextreme-angular/src/ui/chat/index.ts | 26 +++++ .../src/ui/chat/nested/chat-item-dxi.ts | 16 ++- .../src/ui/chat/nested/index.ts | 1 + .../src/ui/chat/nested/item-dxi.ts | 16 ++- .../src/ui/chat/nested/tool-call-dxi.ts | 100 ++++++++++++++++++ 6 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 packages/devextreme-angular/src/ui/chat/nested/tool-call-dxi.ts diff --git a/packages/devextreme-angular/src/core/tokens/index.ts b/packages/devextreme-angular/src/core/tokens/index.ts index b4a8073203e5..976933ab19f1 100644 --- a/packages/devextreme-angular/src/core/tokens/index.ts +++ b/packages/devextreme-angular/src/core/tokens/index.ts @@ -18,6 +18,7 @@ export const PROPERTY_TOKEN_strips = new InjectionToken('property-token- export const PROPERTY_TOKEN_valueAxis = new InjectionToken('property-token-valueAxis'); export const PROPERTY_TOKEN_alerts = new InjectionToken('property-token-alerts'); export const PROPERTY_TOKEN_attachments = new InjectionToken('property-token-attachments'); +export const PROPERTY_TOKEN_toolCalls = new InjectionToken('property-token-toolCalls'); export const PROPERTY_TOKEN_typingUsers = new InjectionToken('property-token-typingUsers'); export const PROPERTY_TOKEN_ranges = new InjectionToken('property-token-ranges'); export const PROPERTY_TOKEN_groupItems = new InjectionToken('property-token-groupItems'); diff --git a/packages/devextreme-angular/src/ui/chat/index.ts b/packages/devextreme-angular/src/ui/chat/index.ts index 353e80f69ded..660ac2298123 100644 --- a/packages/devextreme-angular/src/ui/chat/index.ts +++ b/packages/devextreme-angular/src/ui/chat/index.ts @@ -64,12 +64,14 @@ import { DxoChatSpeechRecognitionConfigModule } from 'devextreme-angular/ui/chat import { DxoChatSpeechToTextOptionsModule } from 'devextreme-angular/ui/chat/nested'; import { DxoChatSuggestionsModule } from 'devextreme-angular/ui/chat/nested'; import { DxiChatSuggestionsItemModule } from 'devextreme-angular/ui/chat/nested'; +import { DxiChatToolCallModule } from 'devextreme-angular/ui/chat/nested'; import { DxiChatTypingUserModule } from 'devextreme-angular/ui/chat/nested'; import { DxoChatUserModule } from 'devextreme-angular/ui/chat/nested'; import { PROPERTY_TOKEN_alerts, PROPERTY_TOKEN_attachments, PROPERTY_TOKEN_items, + PROPERTY_TOKEN_toolCalls, PROPERTY_TOKEN_typingUsers, } from 'devextreme-angular/core/tokens'; @@ -106,6 +108,11 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges this.setChildren('items', value); } + @ContentChildren(PROPERTY_TOKEN_toolCalls) + set _toolCallsContentChildren(value: QueryList) { + this.setChildren('toolCalls', value); + } + @ContentChildren(PROPERTY_TOKEN_typingUsers) set _typingUsersContentChildren(value: QueryList) { this.setChildren('typingUsers', value); @@ -318,6 +325,17 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges this._setOption('reloadOnChange', value); } + /** + * [descr:dxChatOptions.renderToolsInMessageTemplate] + */ + @Input() + get renderToolsInMessageTemplate(): boolean { + return this._getOption('renderToolsInMessageTemplate'); + } + set renderToolsInMessageTemplate(value: boolean) { + this._setOption('renderToolsInMessageTemplate', value); + } + /** * [descr:DOMComponentOptions.rtlEnabled] */ @@ -620,6 +638,11 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges */ @Output() reloadOnChangeChange: EventEmitter; + /** + * This member supports the internal infrastructure and is not intended to be used directly from your code. + */ + @Output() renderToolsInMessageTemplateChange: EventEmitter; + /** * This member supports the internal infrastructure and is not intended to be used directly from your code. */ @@ -728,6 +751,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges { emit: 'messageTemplateChange' }, { emit: 'messageTimestampFormatChange' }, { emit: 'reloadOnChangeChange' }, + { emit: 'renderToolsInMessageTemplateChange' }, { emit: 'rtlEnabledChange' }, { emit: 'sendButtonOptionsChange' }, { emit: 'showAvatarChange' }, @@ -817,6 +841,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges DxoChatSpeechToTextOptionsModule, DxoChatSuggestionsModule, DxiChatSuggestionsItemModule, + DxiChatToolCallModule, DxiChatTypingUserModule, DxoChatUserModule, DxIntegrationModule, @@ -847,6 +872,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges DxoChatSpeechToTextOptionsModule, DxoChatSuggestionsModule, DxiChatSuggestionsItemModule, + DxiChatToolCallModule, DxiChatTypingUserModule, DxoChatUserModule, DxTemplateModule diff --git a/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts b/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts index 332d1c5ad1f8..82a2b6003467 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts @@ -8,7 +8,7 @@ import { ContentChildren, QueryList } from '@angular/core'; -import type { Attachment, User, MessageType } from 'devextreme/ui/chat'; +import type { Attachment, User, ToolCall, MessageType } from 'devextreme/ui/chat'; import { DxIntegrationModule, @@ -20,6 +20,7 @@ import { PROPERTY_TOKEN_items } from 'devextreme-angular/core/tokens'; import { PROPERTY_TOKEN_attachments, + PROPERTY_TOKEN_toolCalls, } from 'devextreme-angular/core/tokens'; @Component({ @@ -40,6 +41,11 @@ export class DxiChatChatItemComponent extends CollectionNestedOption { set _attachmentsContentChildren(value: QueryList) { this.setChildren('attachments', value); } + + @ContentChildren(PROPERTY_TOKEN_toolCalls) + set _toolCallsContentChildren(value: QueryList) { + this.setChildren('toolCalls', value); + } @Input() get alt(): string { @@ -113,6 +119,14 @@ export class DxiChatChatItemComponent extends CollectionNestedOption { this._setOption('timestamp', value); } + @Input() + get toolCalls(): Array { + return this._getOption('toolCalls'); + } + set toolCalls(value: Array) { + this._setOption('toolCalls', value); + } + @Input() get type(): MessageType { return this._getOption('type'); diff --git a/packages/devextreme-angular/src/ui/chat/nested/index.ts b/packages/devextreme-angular/src/ui/chat/nested/index.ts index f0db937f8d34..5de28fe9f0d3 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/index.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/index.ts @@ -13,6 +13,7 @@ export * from './speech-recognition-config'; export * from './speech-to-text-options'; export * from './suggestions-item-dxi'; export * from './suggestions'; +export * from './tool-call-dxi'; export * from './typing-user-dxi'; export * from './user'; diff --git a/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts b/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts index 73eaa9bb7efc..d34bc6002ec9 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts @@ -13,7 +13,7 @@ import { QueryList } from '@angular/core'; import { DOCUMENT } from '@angular/common'; -import type { Attachment, User, MessageType } from 'devextreme/ui/chat'; +import type { Attachment, User, ToolCall, MessageType } from 'devextreme/ui/chat'; import type { ButtonType } from 'devextreme/common'; import { @@ -30,6 +30,7 @@ import { PROPERTY_TOKEN_items } from 'devextreme-angular/core/tokens'; import { PROPERTY_TOKEN_attachments, + PROPERTY_TOKEN_toolCalls, } from 'devextreme-angular/core/tokens'; @Component({ @@ -52,6 +53,11 @@ export class DxiChatItemComponent extends CollectionNestedOption implements Afte set _attachmentsContentChildren(value: QueryList) { this.setChildren('attachments', value); } + + @ContentChildren(PROPERTY_TOKEN_toolCalls) + set _toolCallsContentChildren(value: QueryList) { + this.setChildren('toolCalls', value); + } @Input() get alt(): string { @@ -125,6 +131,14 @@ export class DxiChatItemComponent extends CollectionNestedOption implements Afte this._setOption('timestamp', value); } + @Input() + get toolCalls(): Array { + return this._getOption('toolCalls'); + } + set toolCalls(value: Array) { + this._setOption('toolCalls', value); + } + @Input() get type(): MessageType | ButtonType | string { return this._getOption('type'); diff --git a/packages/devextreme-angular/src/ui/chat/nested/tool-call-dxi.ts b/packages/devextreme-angular/src/ui/chat/nested/tool-call-dxi.ts new file mode 100644 index 000000000000..37810aa968a3 --- /dev/null +++ b/packages/devextreme-angular/src/ui/chat/nested/tool-call-dxi.ts @@ -0,0 +1,100 @@ +/* tslint:disable:max-line-length */ +import { + Component, + NgModule, + Host, + SkipSelf, + Input +} from '@angular/core'; +import type { ToolCallStatus } from 'devextreme/ui/chat'; + +import { + DxIntegrationModule, + NestedOptionHost, +} from 'devextreme-angular/core'; +import { CollectionNestedOption } from 'devextreme-angular/core'; + +import { PROPERTY_TOKEN_toolCalls } from 'devextreme-angular/core/tokens'; + +@Component({ + selector: 'dxi-chat-tool-call', + template: '', + styles: [''], + imports: [ DxIntegrationModule ], + providers: [ + NestedOptionHost, + { + provide: PROPERTY_TOKEN_toolCalls, + useExisting: DxiChatToolCallComponent, + } + ] +}) +export class DxiChatToolCallComponent extends CollectionNestedOption { + @Input() + get arguments(): Record { + return this._getOption('arguments'); + } + set arguments(value: Record) { + this._setOption('arguments', value); + } + + @Input() + get expanded(): boolean { + return this._getOption('expanded'); + } + set expanded(value: boolean) { + this._setOption('expanded', value); + } + + @Input() + get name(): string { + return this._getOption('name'); + } + set name(value: string) { + this._setOption('name', value); + } + + @Input() + get result(): object | string { + return this._getOption('result'); + } + set result(value: object | string) { + this._setOption('result', value); + } + + @Input() + get status(): ToolCallStatus { + return this._getOption('status'); + } + set status(value: ToolCallStatus) { + this._setOption('status', value); + } + + + protected get _optionPath() { + return 'toolCalls'; + } + + constructor(@SkipSelf() @Host() parentOptionHost: NestedOptionHost, + @Host() optionHost: NestedOptionHost) { + super(); + parentOptionHost.setNestedOption(this); + optionHost.setHost(this, this._fullOptionPath.bind(this)); + } + + + + ngOnDestroy() { + this._deleteRemovedOptions(this._fullOptionPath()); + } +} + +@NgModule({ + imports: [ + DxiChatToolCallComponent + ], + exports: [ + DxiChatToolCallComponent + ], +}) +export class DxiChatToolCallModule { } From 7641d83891b44d5bda5730432c96656c0e8bb830 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 11:45:24 +0300 Subject: [PATCH 4/9] React and Vue: add toolCalls to the chat items and the renderToolsInMessageTemplate option --- packages/devextreme-react/src/chat.ts | 33 +++++++++++++++++++-- packages/devextreme-vue/src/chat.ts | 42 +++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/packages/devextreme-react/src/chat.ts b/packages/devextreme-react/src/chat.ts index 9ee42ffca9ad..d5df1ea07512 100644 --- a/packages/devextreme-react/src/chat.ts +++ b/packages/devextreme-react/src/chat.ts @@ -8,7 +8,7 @@ import dxChat, { import { Component as BaseComponent, IHtmlOptions, ComponentRef, NestedComponentMeta } from "./core/component"; import NestedOption from "./core/nested-option"; -import type { Message, AttachmentDownloadClickEvent, DisposingEvent, InitializedEvent, MessageDeletedEvent, MessageDeletingEvent, MessageEditCanceledEvent, MessageEditingStartEvent, MessageEnteredEvent, MessageUpdatedEvent, MessageUpdatingEvent, TypingEndEvent, TypingStartEvent, Attachment as ChatAttachment, User as ChatUser, MessageType, SendButtonAction, SendButtonClickEvent } from "devextreme/ui/chat"; +import type { Message, AttachmentDownloadClickEvent, DisposingEvent, InitializedEvent, MessageDeletedEvent, MessageDeletingEvent, MessageEditCanceledEvent, MessageEditingStartEvent, MessageEnteredEvent, MessageUpdatedEvent, MessageUpdatingEvent, TypingEndEvent, TypingStartEvent, Attachment as ChatAttachment, User as ChatUser, MessageType, SendButtonAction, SendButtonClickEvent, ToolCall as ChatToolCall, ToolCallStatus } from "devextreme/ui/chat"; import type { DisposingEvent as FileUploaderDisposingEvent, InitializedEvent as FileUploaderInitializedEvent, BeforeSendEvent, ContentReadyEvent, DropZoneEnterEvent, DropZoneLeaveEvent, FilesUploadedEvent, OptionChangedEvent, ProgressEvent, UploadAbortedEvent, UploadedEvent, UploadErrorEvent, UploadStartedEvent, ValueChangedEvent, UploadHttpMethod, FileUploadMode } from "devextreme/ui/file_uploader"; import type { DisposingEvent as SpeechToTextDisposingEvent, InitializedEvent as SpeechToTextInitializedEvent, ContentReadyEvent as SpeechToTextContentReadyEvent, OptionChangedEvent as SpeechToTextOptionChangedEvent, CustomSpeechRecognizer as SpeechToTextCustomSpeechRecognizer, EndEvent, ErrorEvent, ResultEvent, StartClickEvent, StopClickEvent, SpeechRecognitionConfig as SpeechToTextSpeechRecognitionConfig } from "devextreme/ui/speech_to_text"; import type { DisposingEvent as ButtonGroupDisposingEvent, InitializedEvent as ButtonGroupInitializedEvent, ContentReadyEvent as ButtonGroupContentReadyEvent, OptionChangedEvent as ButtonGroupOptionChangedEvent, dxButtonGroupItem, ItemClickEvent, SelectionChangedEvent } from "devextreme/ui/button_group"; @@ -188,6 +188,7 @@ type IChatItemProps = React.PropsWithChildren<{ src?: string; text?: string; timestamp?: Date | number | string; + toolCalls?: Array; type?: MessageType; }> const _componentChatItem = (props: IChatItemProps) => { @@ -198,7 +199,8 @@ const _componentChatItem = (props: IChatItemProps) => { IsCollectionItem: true, ExpectedChildren: { attachment: { optionName: "attachments", isCollectionItem: true }, - author: { optionName: "author", isCollectionItem: false } + author: { optionName: "author", isCollectionItem: false }, + toolCall: { optionName: "toolCalls", isCollectionItem: true } }, }, }); @@ -369,6 +371,7 @@ type IItemProps = React.PropsWithChildren<{ src?: string; text?: string; timestamp?: Date | number | string; + toolCalls?: Array; type?: MessageType | ButtonType | string; disabled?: boolean; elementAttr?: Record; @@ -387,7 +390,8 @@ const _componentItem = (props: IItemProps) => { IsCollectionItem: true, ExpectedChildren: { attachment: { optionName: "attachments", isCollectionItem: true }, - author: { optionName: "author", isCollectionItem: false } + author: { optionName: "author", isCollectionItem: false }, + toolCall: { optionName: "toolCalls", isCollectionItem: true } }, TemplateProps: [{ tmplOption: "template", @@ -612,6 +616,27 @@ const SuggestionsItem = Object.assign; + expanded?: boolean; + name?: string; + result?: Record | string; + status?: ToolCallStatus; +}> +const _componentToolCall = (props: IToolCallProps) => { + return React.createElement(NestedOption, { + ...props, + elementDescriptor: { + OptionName: "toolCalls", + IsCollectionItem: true, + }, + }); +}; + +const ToolCall = Object.assign(_componentToolCall, { + componentType: "option", +}); + // owners: // Chat type ITypingUserProps = React.PropsWithChildren<{ @@ -690,6 +715,8 @@ export { ISuggestionsProps, SuggestionsItem, ISuggestionsItemProps, + ToolCall, + IToolCallProps, TypingUser, ITypingUserProps, User, diff --git a/packages/devextreme-vue/src/chat.ts b/packages/devextreme-vue/src/chat.ts index 4199b8b5c364..008ee203b24e 100644 --- a/packages/devextreme-vue/src/chat.ts +++ b/packages/devextreme-vue/src/chat.ts @@ -25,9 +25,11 @@ import { SendButtonProperties, User, Attachment, + ToolCall, MessageType, SendButtonAction, SendButtonClickEvent, + ToolCallStatus, } from "devextreme/ui/chat"; import { DataSourceOptions, @@ -125,6 +127,7 @@ type AccessibleOptions = Pick void)>, onTypingStart: Function as PropType<((e: TypingStartEvent) => void)>, reloadOnChange: Boolean, + renderToolsInMessageTemplate: Boolean, rtlEnabled: Boolean, sendButtonOptions: Object as PropType>, showAvatar: Boolean, @@ -229,6 +233,7 @@ const componentConfig = { "update:onTypingEnd": null, "update:onTypingStart": null, "update:reloadOnChange": null, + "update:renderToolsInMessageTemplate": null, "update:rtlEnabled": null, "update:sendButtonOptions": null, "update:showAvatar": null, @@ -349,6 +354,7 @@ const DxChatItemConfig = { "update:src": null, "update:text": null, "update:timestamp": null, + "update:toolCalls": null, "update:type": null, }, props: { @@ -361,6 +367,7 @@ const DxChatItemConfig = { src: String, text: String, timestamp: [Date, Number, String], + toolCalls: Array as PropType>, type: String as PropType } }; @@ -373,7 +380,8 @@ const DxChatItem = defineComponent(DxChatItemConfig); (DxChatItem as any).$_isCollectionItem = true; (DxChatItem as any).$_expectedChildren = { attachment: { isCollectionItem: true, optionName: "attachments" }, - author: { isCollectionItem: false, optionName: "author" } + author: { isCollectionItem: false, optionName: "author" }, + toolCall: { isCollectionItem: true, optionName: "toolCalls" } }; const DxCustomSpeechRecognizerConfig = { @@ -604,6 +612,7 @@ const DxItemConfig = { "update:template": null, "update:text": null, "update:timestamp": null, + "update:toolCalls": null, "update:type": null, "update:visible": null, }, @@ -622,6 +631,7 @@ const DxItemConfig = { template: {}, text: String, timestamp: [Date, Number, String], + toolCalls: Array as PropType>, type: String as PropType, visible: Boolean } @@ -635,7 +645,8 @@ const DxItem = defineComponent(DxItemConfig); (DxItem as any).$_isCollectionItem = true; (DxItem as any).$_expectedChildren = { attachment: { isCollectionItem: true, optionName: "attachments" }, - author: { isCollectionItem: false, optionName: "author" } + author: { isCollectionItem: false, optionName: "author" }, + toolCall: { isCollectionItem: true, optionName: "toolCalls" } }; const DxMessageTimestampFormatConfig = { @@ -891,6 +902,32 @@ const DxSuggestionsItem = defineComponent(DxSuggestionsItemConfig); (DxSuggestionsItem as any).$_optionName = "items"; (DxSuggestionsItem as any).$_isCollectionItem = true; +const DxToolCallConfig = { + emits: { + "update:isActive": null, + "update:hoveredElement": null, + "update:arguments": null, + "update:expanded": null, + "update:name": null, + "update:result": null, + "update:status": null, + }, + props: { + arguments: Object as PropType>, + expanded: Boolean, + name: String, + result: [Object, String] as PropType, + status: String as PropType + } +}; + +prepareConfigurationComponentConfig(DxToolCallConfig); + +const DxToolCall = defineComponent(DxToolCallConfig); + +(DxToolCall as any).$_optionName = "toolCalls"; +(DxToolCall as any).$_isCollectionItem = true; + const DxTypingUserConfig = { emits: { "update:isActive": null, @@ -956,6 +993,7 @@ export { DxSpeechToTextOptions, DxSuggestions, DxSuggestionsItem, + DxToolCall, DxTypingUser, DxUser }; From f5a84bdfb8badface211c7dbcffe203c23d18d44 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 13:19:18 +0300 Subject: [PATCH 5/9] Chat: replace the renderToolsInMessageTemplate option with toolCallOptions --- packages/devextreme/js/ui/chat.d.ts | 31 +++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/devextreme/js/ui/chat.d.ts b/packages/devextreme/js/ui/chat.d.ts index b09500aca2a3..8346ef852a25 100644 --- a/packages/devextreme/js/ui/chat.d.ts +++ b/packages/devextreme/js/ui/chat.d.ts @@ -291,6 +291,26 @@ export type ToolCall = { [key: string]: any; }; +/** + * @docid + * @namespace DevExpress.ui.dxChat + * @public + */ +export type ToolCallOptions = { + /** + * @docid + * @default false + * @public + */ + showInMessageTemplate?: boolean; + /** + * @docid + * @default false + * @public + */ + expandAll?: boolean; +}; + /** * @docid * @namespace DevExpress.ui.dxChat @@ -545,12 +565,6 @@ export interface dxChatOptions extends WidgetOptions { * @public */ reloadOnChange?: boolean; - /** - * @docid - * @default false - * @public - */ - renderToolsInMessageTemplate?: boolean; /** * @docid * @public @@ -598,6 +612,11 @@ export interface dxChatOptions extends WidgetOptions { * @public */ suggestions?: Omit; + /** + * @docid + * @public + */ + toolCallOptions?: ToolCallOptions; /** * @docid * @default [] From 2d3657b22322ef919f1bd88dcf46906e419abd70 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 13:21:25 +0300 Subject: [PATCH 6/9] Chat: update the generated d.ts bundle and the reexports --- packages/devextreme/js/ui/chat_types.d.ts | 1 + packages/devextreme/ts/dx.all.d.ts | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/ui/chat_types.d.ts b/packages/devextreme/js/ui/chat_types.d.ts index 13c0b065323c..cc49bcf8ac15 100644 --- a/packages/devextreme/js/ui/chat_types.d.ts +++ b/packages/devextreme/js/ui/chat_types.d.ts @@ -19,6 +19,7 @@ export { Attachment, ToolCallStatus, ToolCall, + ToolCallOptions, MessageType, TextMessage, ImageMessage, diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index cc31a48dc825..2f079225a403 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -11860,10 +11860,6 @@ declare module DevExpress.ui { * [descr:dxChatOptions.reloadOnChange] */ reloadOnChange?: boolean; - /** - * [descr:dxChatOptions.renderToolsInMessageTemplate] - */ - renderToolsInMessageTemplate?: boolean; /** * [descr:dxChatOptions.sendButtonOptions] */ @@ -11905,6 +11901,10 @@ declare module DevExpress.ui { | 'selectedItems' | 'onSelectionChanged' >; + /** + * [descr:dxChatOptions.toolCallOptions] + */ + toolCallOptions?: DevExpress.ui.dxChat.ToolCallOptions; /** * [descr:dxChatOptions.typingUsers] */ @@ -35038,6 +35038,19 @@ declare module DevExpress.ui.dxChat { [key: string]: any; }; + /** + * [descr:ToolCallOptions] + */ + export type ToolCallOptions = { + /** + * [descr:ToolCallOptions.showInMessageTemplate] + */ + showInMessageTemplate?: boolean; + /** + * [descr:ToolCallOptions.expandAll] + */ + expandAll?: boolean; + }; /** * [descr:ToolCallStatus] */ From b6c8a69dc31544bf7820cffb7b0be1975e02d6c7 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 13:24:12 +0300 Subject: [PATCH 7/9] Angular: replace renderToolsInMessageTemplate with toolCallOptions --- .../devextreme-angular/src/ui/chat/index.ts | 37 +++++----- .../src/ui/chat/nested/index.ts | 1 + .../src/ui/chat/nested/tool-call-options.ts | 73 +++++++++++++++++++ 3 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 packages/devextreme-angular/src/ui/chat/nested/tool-call-options.ts diff --git a/packages/devextreme-angular/src/ui/chat/index.ts b/packages/devextreme-angular/src/ui/chat/index.ts index 660ac2298123..3dd48443cff9 100644 --- a/packages/devextreme-angular/src/ui/chat/index.ts +++ b/packages/devextreme-angular/src/ui/chat/index.ts @@ -19,7 +19,7 @@ import { } from '@angular/core'; -import type { default as dxChat, Alert, Message, AttachmentDownloadClickEvent, DisposingEvent, InitializedEvent, InputFieldTextChangedEvent, MessageDeletedEvent, MessageDeletingEvent, MessageEditCanceledEvent, MessageEditingStartEvent, MessageEnteredEvent, MessageUpdatedEvent, MessageUpdatingEvent, OptionChangedEvent, TypingEndEvent, TypingStartEvent, SendButtonProperties, User } from 'devextreme/ui/chat'; +import type { default as dxChat, Alert, Message, AttachmentDownloadClickEvent, DisposingEvent, InitializedEvent, InputFieldTextChangedEvent, MessageDeletedEvent, MessageDeletingEvent, MessageEditCanceledEvent, MessageEditingStartEvent, MessageEnteredEvent, MessageUpdatedEvent, MessageUpdatingEvent, OptionChangedEvent, TypingEndEvent, TypingStartEvent, SendButtonProperties, ToolCallOptions, User } from 'devextreme/ui/chat'; import type { default as DataSource, DataSourceOptions } from 'devextreme/data/data_source'; import type { Store } from 'devextreme/data/store'; import type { Format } from 'devextreme/common/core/localization'; @@ -65,6 +65,7 @@ import { DxoChatSpeechToTextOptionsModule } from 'devextreme-angular/ui/chat/nes import { DxoChatSuggestionsModule } from 'devextreme-angular/ui/chat/nested'; import { DxiChatSuggestionsItemModule } from 'devextreme-angular/ui/chat/nested'; import { DxiChatToolCallModule } from 'devextreme-angular/ui/chat/nested'; +import { DxoChatToolCallOptionsModule } from 'devextreme-angular/ui/chat/nested'; import { DxiChatTypingUserModule } from 'devextreme-angular/ui/chat/nested'; import { DxoChatUserModule } from 'devextreme-angular/ui/chat/nested'; import { @@ -325,17 +326,6 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges this._setOption('reloadOnChange', value); } - /** - * [descr:dxChatOptions.renderToolsInMessageTemplate] - */ - @Input() - get renderToolsInMessageTemplate(): boolean { - return this._getOption('renderToolsInMessageTemplate'); - } - set renderToolsInMessageTemplate(value: boolean) { - this._setOption('renderToolsInMessageTemplate', value); - } - /** * [descr:DOMComponentOptions.rtlEnabled] */ @@ -429,6 +419,15 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges this._setOption('suggestions', value); } + + @Input() + get toolCallOptions(): ToolCallOptions { + return this._getOption('toolCallOptions'); + } + set toolCallOptions(value: ToolCallOptions) { + this._setOption('toolCallOptions', value); + } + /** * [descr:dxChatOptions.typingUsers] */ @@ -638,11 +637,6 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges */ @Output() reloadOnChangeChange: EventEmitter; - /** - * This member supports the internal infrastructure and is not intended to be used directly from your code. - */ - @Output() renderToolsInMessageTemplateChange: EventEmitter; - /** * This member supports the internal infrastructure and is not intended to be used directly from your code. */ @@ -688,6 +682,11 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges */ @Output() suggestionsChange: EventEmitter; + /** + * This member supports the internal infrastructure and is not intended to be used directly from your code. + */ + @Output() toolCallOptionsChange: EventEmitter; + /** * This member supports the internal infrastructure and is not intended to be used directly from your code. */ @@ -751,7 +750,6 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges { emit: 'messageTemplateChange' }, { emit: 'messageTimestampFormatChange' }, { emit: 'reloadOnChangeChange' }, - { emit: 'renderToolsInMessageTemplateChange' }, { emit: 'rtlEnabledChange' }, { emit: 'sendButtonOptionsChange' }, { emit: 'showAvatarChange' }, @@ -761,6 +759,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges { emit: 'speechToTextEnabledChange' }, { emit: 'speechToTextOptionsChange' }, { emit: 'suggestionsChange' }, + { emit: 'toolCallOptionsChange' }, { emit: 'typingUsersChange' }, { emit: 'userChange' }, { emit: 'visibleChange' }, @@ -842,6 +841,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges DxoChatSuggestionsModule, DxiChatSuggestionsItemModule, DxiChatToolCallModule, + DxoChatToolCallOptionsModule, DxiChatTypingUserModule, DxoChatUserModule, DxIntegrationModule, @@ -873,6 +873,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges DxoChatSuggestionsModule, DxiChatSuggestionsItemModule, DxiChatToolCallModule, + DxoChatToolCallOptionsModule, DxiChatTypingUserModule, DxoChatUserModule, DxTemplateModule diff --git a/packages/devextreme-angular/src/ui/chat/nested/index.ts b/packages/devextreme-angular/src/ui/chat/nested/index.ts index 5de28fe9f0d3..6c58bc1a2cf3 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/index.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/index.ts @@ -14,6 +14,7 @@ export * from './speech-to-text-options'; export * from './suggestions-item-dxi'; export * from './suggestions'; export * from './tool-call-dxi'; +export * from './tool-call-options'; export * from './typing-user-dxi'; export * from './user'; diff --git a/packages/devextreme-angular/src/ui/chat/nested/tool-call-options.ts b/packages/devextreme-angular/src/ui/chat/nested/tool-call-options.ts new file mode 100644 index 000000000000..4f345ec9cc51 --- /dev/null +++ b/packages/devextreme-angular/src/ui/chat/nested/tool-call-options.ts @@ -0,0 +1,73 @@ +/* tslint:disable:max-line-length */ +import { + Component, + OnInit, + OnDestroy, + NgModule, + Host, + SkipSelf, + Input +} from '@angular/core'; + +import { + DxIntegrationModule, + NestedOptionHost, +} from 'devextreme-angular/core'; +import { NestedOption } from 'devextreme-angular/core'; + +@Component({ + selector: 'dxo-chat-tool-call-options', + template: '', + styles: [''], + imports: [ DxIntegrationModule ], + providers: [NestedOptionHost] +}) +export class DxoChatToolCallOptionsComponent extends NestedOption implements OnDestroy, OnInit { + @Input() + get expandAll(): boolean { + return this._getOption('expandAll'); + } + set expandAll(value: boolean) { + this._setOption('expandAll', value); + } + + @Input() + get showInMessageTemplate(): boolean { + return this._getOption('showInMessageTemplate'); + } + set showInMessageTemplate(value: boolean) { + this._setOption('showInMessageTemplate', value); + } + + + protected get _optionPath() { + return 'toolCallOptions'; + } + + constructor(@SkipSelf() @Host() parentOptionHost: NestedOptionHost, + @Host() optionHost: NestedOptionHost) { + super(); + parentOptionHost.setNestedOption(this); + optionHost.setHost(this, this._fullOptionPath.bind(this)); + } + + + ngOnInit() { + this._addRecreatedComponent(); + } + + ngOnDestroy() { + this._addRemovedOption(this._getOptionPath()); + } + +} + +@NgModule({ + imports: [ + DxoChatToolCallOptionsComponent + ], + exports: [ + DxoChatToolCallOptionsComponent + ], +}) +export class DxoChatToolCallOptionsModule { } From 73b1f19dd1ba2776530119fa63eb4b030c1214c4 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 13:26:22 +0300 Subject: [PATCH 8/9] React and Vue: replace renderToolsInMessageTemplate with toolCallOptions --- packages/devextreme-react/src/chat.ts | 22 +++++++++++++++++++++ packages/devextreme-vue/src/chat.ts | 28 ++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/devextreme-react/src/chat.ts b/packages/devextreme-react/src/chat.ts index d5df1ea07512..4e3e24942f1b 100644 --- a/packages/devextreme-react/src/chat.ts +++ b/packages/devextreme-react/src/chat.ts @@ -81,6 +81,7 @@ const Chat = memo( sendButtonOptions: { optionName: "sendButtonOptions", isCollectionItem: false }, speechToTextOptions: { optionName: "speechToTextOptions", isCollectionItem: false }, suggestions: { optionName: "suggestions", isCollectionItem: false }, + toolCallOptions: { optionName: "toolCallOptions", isCollectionItem: false }, typingUser: { optionName: "typingUsers", isCollectionItem: true }, user: { optionName: "user", isCollectionItem: false } }), []); @@ -637,6 +638,25 @@ const ToolCall = Object.assign(_ componentType: "option", }); +// owners: +// Chat +type IToolCallOptionsProps = React.PropsWithChildren<{ + expandAll?: boolean; + showInMessageTemplate?: boolean; +}> +const _componentToolCallOptions = (props: IToolCallOptionsProps) => { + return React.createElement(NestedOption, { + ...props, + elementDescriptor: { + OptionName: "toolCallOptions", + }, + }); +}; + +const ToolCallOptions = Object.assign(_componentToolCallOptions, { + componentType: "option", +}); + // owners: // Chat type ITypingUserProps = React.PropsWithChildren<{ @@ -717,6 +737,8 @@ export { ISuggestionsItemProps, ToolCall, IToolCallProps, + ToolCallOptions, + IToolCallOptionsProps, TypingUser, ITypingUserProps, User, diff --git a/packages/devextreme-vue/src/chat.ts b/packages/devextreme-vue/src/chat.ts index 008ee203b24e..526c798d09a1 100644 --- a/packages/devextreme-vue/src/chat.ts +++ b/packages/devextreme-vue/src/chat.ts @@ -23,6 +23,7 @@ import { TypingEndEvent, TypingStartEvent, SendButtonProperties, + ToolCallOptions, User, Attachment, ToolCall, @@ -127,7 +128,6 @@ type AccessibleOptions = Pick void)>, onTypingStart: Function as PropType<((e: TypingStartEvent) => void)>, reloadOnChange: Boolean, - renderToolsInMessageTemplate: Boolean, rtlEnabled: Boolean, sendButtonOptions: Object as PropType>, showAvatar: Boolean, @@ -192,6 +192,7 @@ const componentConfig = { speechToTextEnabled: Boolean, speechToTextOptions: Object as PropType>, suggestions: Object as PropType>, + toolCallOptions: Object as PropType>, typingUsers: Array as PropType>, user: Object as PropType>, visible: Boolean, @@ -233,7 +234,6 @@ const componentConfig = { "update:onTypingEnd": null, "update:onTypingStart": null, "update:reloadOnChange": null, - "update:renderToolsInMessageTemplate": null, "update:rtlEnabled": null, "update:sendButtonOptions": null, "update:showAvatar": null, @@ -243,6 +243,7 @@ const componentConfig = { "update:speechToTextEnabled": null, "update:speechToTextOptions": null, "update:suggestions": null, + "update:toolCallOptions": null, "update:typingUsers": null, "update:user": null, "update:visible": null, @@ -267,6 +268,7 @@ const componentConfig = { sendButtonOptions: { isCollectionItem: false, optionName: "sendButtonOptions" }, speechToTextOptions: { isCollectionItem: false, optionName: "speechToTextOptions" }, suggestions: { isCollectionItem: false, optionName: "suggestions" }, + toolCallOptions: { isCollectionItem: false, optionName: "toolCallOptions" }, typingUser: { isCollectionItem: true, optionName: "typingUsers" }, user: { isCollectionItem: false, optionName: "user" } }; @@ -928,6 +930,25 @@ const DxToolCall = defineComponent(DxToolCallConfig); (DxToolCall as any).$_optionName = "toolCalls"; (DxToolCall as any).$_isCollectionItem = true; +const DxToolCallOptionsConfig = { + emits: { + "update:isActive": null, + "update:hoveredElement": null, + "update:expandAll": null, + "update:showInMessageTemplate": null, + }, + props: { + expandAll: Boolean, + showInMessageTemplate: Boolean + } +}; + +prepareConfigurationComponentConfig(DxToolCallOptionsConfig); + +const DxToolCallOptions = defineComponent(DxToolCallOptionsConfig); + +(DxToolCallOptions as any).$_optionName = "toolCallOptions"; + const DxTypingUserConfig = { emits: { "update:isActive": null, @@ -994,6 +1015,7 @@ export { DxSuggestions, DxSuggestionsItem, DxToolCall, + DxToolCallOptions, DxTypingUser, DxUser }; From e29263b8a1a3ffebe96e50d4283d20bdea8a13e1 Mon Sep 17 00:00:00 2001 From: dmlvr Date: Fri, 23 Oct 2026 17:35:59 +0300 Subject: [PATCH 9/9] fix by review --- .../devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts | 2 +- packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts | 2 +- packages/devextreme-metadata/make-angular-metadata.ts | 1 + packages/devextreme/js/ui/chat.d.ts | 3 +-- packages/devextreme/ts/dx.all.d.ts | 3 --- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts b/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts index 82a2b6003467..9aad82e42b01 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/chat-item-dxi.ts @@ -41,7 +41,7 @@ export class DxiChatChatItemComponent extends CollectionNestedOption { set _attachmentsContentChildren(value: QueryList) { this.setChildren('attachments', value); } - + @ContentChildren(PROPERTY_TOKEN_toolCalls) set _toolCallsContentChildren(value: QueryList) { this.setChildren('toolCalls', value); diff --git a/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts b/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts index d34bc6002ec9..fa4a6db03ce5 100644 --- a/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts +++ b/packages/devextreme-angular/src/ui/chat/nested/item-dxi.ts @@ -53,7 +53,7 @@ export class DxiChatItemComponent extends CollectionNestedOption implements Afte set _attachmentsContentChildren(value: QueryList) { this.setChildren('attachments', value); } - + @ContentChildren(PROPERTY_TOKEN_toolCalls) set _toolCallsContentChildren(value: QueryList) { this.setChildren('toolCalls', value); diff --git a/packages/devextreme-metadata/make-angular-metadata.ts b/packages/devextreme-metadata/make-angular-metadata.ts index 791b014255aa..05dd77dddcb4 100644 --- a/packages/devextreme-metadata/make-angular-metadata.ts +++ b/packages/devextreme-metadata/make-angular-metadata.ts @@ -55,6 +55,7 @@ Ng.makeMetadata({ removeMembers(/\/chat:MessageType/), removeMembers(/\/chat:MessageBase.type/), removeMembers(/\/chat:TextMessage.attachments/), + removeMembers(/\/chat:TextMessage.toolCalls/), removeMembers( /\/chat:dxChatOptions\.(fileUploaderOptions|inputFieldText|sendButtonOptions|speechToTextOptions|suggestions|onAttachmentDownloadClick)/, ), diff --git a/packages/devextreme/js/ui/chat.d.ts b/packages/devextreme/js/ui/chat.d.ts index 8346ef852a25..f1dd0162f1fb 100644 --- a/packages/devextreme/js/ui/chat.d.ts +++ b/packages/devextreme/js/ui/chat.d.ts @@ -257,7 +257,6 @@ export type Attachment = { export type ToolCallStatus = 'success' | 'error'; /** - * @docid * @namespace DevExpress.ui.dxChat * @public */ @@ -270,6 +269,7 @@ export type ToolCall = { /** * @docid * @public + * @type object */ arguments?: Record; /** @@ -380,7 +380,6 @@ export type TextMessage = MessageBase & { /** * @docid * @public - * @type Array */ toolCalls?: ToolCall[]; diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index 2f079225a403..3a6b67578fc2 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -35011,9 +35011,6 @@ declare module DevExpress.ui.dxChat { [key: string]: any; }; - /** - * [descr:ToolCall] - */ export type ToolCall = { /** * [descr:ToolCall.name]