Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Round-7 sync: Error states as bubbles section + cache-write asymmetry note + JSON-envelope-still-for-audit callout (TDEV-1564)

Display a chat conversation thread between an end-user and an AI model.

ReferenceControlsInteraction → ChatSession


The ChatSession control belongs to the Interaction category and runs on TChatSession control (shown in the Designer Components Panel under the Interaction category as "ChatSession") is the FrameworX surface for an AI chat panel inside a Display. It belongs to the Portable rendering target (WPF rich client and HTML5/WASM). Place it on a Display from the Components Panel and configure the properties listed below.ChatSession renders a vertical, auto-scrolling list of message bubbles, visually distinguishing user messages from AI messages. It is the standard FrameworX surface for an operator chat or LLM-assistant pane inside a SCADA/HMI Display— the same control renders identically in the WPF Rich Client and in the HTML5/WASM Web Client.

In FrameworX 10.1.5 the control is zero-substrate for the standard pattern: drop a TChatSession on a Display, drop a TextBox bound to a Query tag, drop a Button with the ChatRequest Action, and the live conversation appears multi-turn and role-bubbled without any DataTable, UserType, or Script wiring on the adopter side.

Table of Contents
maxLevel3
stylenone


Overview

ChatSession is the FrameworX Display control for conversational AI inside a process-control or operator console. It renders a scrolling thread of message bubbles bound to an items source — typically the platform-managed TChatSession renders an auto-scrolling vertical thread of per-role message bubbles. The control pulls the conversation directly from the runtime's per-Display-panel transcript from cache — the same cache the ChatRequest Action Reference action , a Dataset table, a List-typed Tag, or a Script-returned collection — where each item carries a role (user vs AI) and a body text. The control inspects each item's role value, compares it against UserRoleValue and AIRoleValue, and styles the bubble accordingly (alignment, colors, corner shaping).

Primary pattern — ChatRequest with auto-managed transcript

In FrameworX 10.1.5, the standard operator chat panel pairs ChatSession with the ChatRequest Display Action. No scripting is required:

  • A TextBox for the user prompt and a Button whose Action is set to ChatRequest (Query tag, Return tag configured in the Action editor).

  • A ChatSession control bound to the same Display panel. The platform automatically maintains the per-Display-panel transcript — each turn the operator sends is appended to the conversation history server-side; the AI reply is appended after the model responds. The customer does not need to write Script code to manage this collection.

The per-Display-panel transcript is keyed internally by the client connection and resets transparently on operator login change (shift change). It can be disabled solution-wide via the EnableChatHistory bit on SolutionSettings.ModelOptions. See ChatRequest Action Reference for full transcript semantics.

Alternative pattern — Script-managed collection

When the conversation source is not the platform-managed transcript — for example, a persisted chat log driven by a Dataset, or a custom in-memory collection a Script assembles — a typical assistant pane wires three pieces:

  • A TextBox for the user prompt and a Button whose Action invokes a Script.

  • A Server-side Script that appends the user message to the conversation collection, then calls an LLM via the FrameworX HTTP CHAT verb (routed through the in-product ChatSession orchestrator and the ChatRequest API). On response, the Script appends the AI reply to the same collection.

  • A ChatSession control bound to that collection. The control re-renders on any collection change, and — when AutoScrollToBottom is true — brings the newest message into view automatically.

Because the control runs on the Portable target, the same Display works in the WPF Rich Client and in the HTML5/WASM Smart Client without modification.

Bindings

ChatSession uses the standard FrameworX itemized-source pattern. The conversation collection is provided through three coordinated properties:

Property

Use in an AI chat pattern

ItemsSourceType

Selects the kind of source. Use DataTable when conversations are persisted (Dataset Query or Table holding one row per message); use ArrayTag when the conversation lives in memory as a List-typed Tag; use Text for a static seeded thread.

ItemsSourceLink

The actual source reference, interpreted per ItemsSourceType. For persisted chats: @Dataset.Query.ConversationByUser (or similar). For in-memory chats: @Tag.ChatThread where ChatThread is a List Tag whose item members include a role field and a body field. The control re-renders on collection change.

ItemsSourceOption

Legacy source-selection mode kept for compatibility; new Displays should prefer ItemsSourceType + ItemsSourceLink.

Whichever source is chosen, each item must expose a role value comparable to UserRoleValue / AIRoleValue and a body text. For Dataset sources, name the role column and body column to match what the Script appends; for List-Tag sources, define a UserType with at least Role and Body members

populates on every chat turn. There is no transcript Tag to bind, no DataTable to configure, no UserType to define, and no Server Script glue to write.

This is the standard pattern for every chat surface in FrameworX: operator chat, knowledge-graph assistant, SupportAI debug, partner portal, training tutor. Each surface composes the same five elements (TChatSession + Input TextBox + Send/Clear/Compress Buttons + scalar Query/Reply Tags) and re-skins independently.

Minimum operator chat panel — the zero-substrate pattern

Three elements, two scalar tags, one Action. No scripting:

  1. A TextBox whose write binding is a String tag (e.g. @Tag.Chat/Query).

  2. A Button with an Action dynamic of type ChatRequest. Set the Action's Query field to the Query tag and the Return field to a JSON tag (e.g. @Tag.Chat/Reply).

  3. A TChatSession control on the same Display panel. Leave ItemsSourceLink empty — the control auto-resolves to the live transcript for the current client.

When the operator clicks the Button, the live conversation appears in the TChatSession: the user's question lands immediately as an accent-tinted bubble (no waiting for the LLM), a rotating ? pending indicator with an elapsed-seconds counter follows it, and the assistant reply bubble replaces the indicator when the model finishes. Follow-up questions on the same panel retain context — the model sees the full transcript and can refer back to earlier turns.

For a complete working solution showing this pattern end-to-end — six live plant tags as grounding context, three quick-prompt buttons, the AI Engine tile configured for a local Ollama model — see Chat Session Example.


Visual contract

The control's render surface is opinionated — the visual shape is pinned by the platform so every chat surface in FrameworX reads consistently. Authors do not style the bubbles individually; they style the control's outer chrome (background, border) and the platform paints the bubbles per role.

Layout — single-column-left

Every bubble — user, assistant, and unknown-role — left-edges in a single column. Color discriminates role; alignment does not. The layout follows the conversational-AI cluster convention (Claude Code, Claude.ai, ChatGPT, Cursor, GitHub Copilot, Linear AI) rather than the peer-to-peer messenger convention (iMessage, WhatsApp, Slack DMs). Each bubble caps at ~75 % of the control's rendered width; the rest of the row is empty so the eye scans one ragged-right margin instead of two.

Bubble shape — selectable TTextBlock

Bubble bodies render as T.Wpf.RunControls.TTextBlock elements (the FrameworX-native control that inherits System.Windows.Controls.TextBlock). Chrome is suppressed by the control — no border, no focus rectangle, no caret, no keyboard tab-stop.

Bubble text is selectable. Operators drag-select bubble text with the mouse, then press Ctrl-C to copy to the clipboard, or right-click and pick Copy from the context menu. Selection works symmetrically on user and assistant bubbles. The capability is enabled via TextBlock.IsTextSelectionEnabled on WPF .NET 4.8; on HTML5/WASM (OpenSilver) it degrades gracefully — the bubbles render correctly and selection activates as soon as OpenSilver surfaces the underlying property.

Color palette — theme tokens, not RGB

Role

Background

Foreground (text)

Border

User

AccentBrush (platform accent surface)

ThemeWhiteBrush (high-contrast text on accent)

DefaultBorder

Assistant

ShadeBrush (neutral shade)

TextForeground

DefaultBorder

Unknown (Role matches neither UserRoleValue nor AIRoleValue)

ShadeBrush

TextForeground

DefaultBorder

The control resolves these theme tokens dynamically — a live theme switch repaints every bubble without a transcript reload, via the platform's ThemeDP attached-property surface. Authors should not hardcode bubble RGB values; the theme tokens are the contract.

Sizing — auto-size to wrapped content

Bubbles auto-size to their wrapped content (Height = NaN, MinHeight = 22) so multi-line replies grow vertically without being clipped. The horizontal cap is ~75 % of TChatSession.ActualWidth (the outer control), so wide screens render correctly without re-skinning and narrow screens wrap rather than horizontally scroll.

Corner shaping — BubbleCornerRadius

Default 14 pixels. Set to 0 for square bubbles, higher values for a more conversational appearance. Applies uniformly to user and assistant bubbles.

Auto-scroll — AutoScrollToBottom

Default true. On every transcript update (new turn lands, ChatCompress replaces, initial open with non-empty cache) the inner ScrollViewer scrolls to the bottom so the freshest message is in view. Set to false when the user is reviewing historical transcript and the scroll position should be preserved.

Pending-indicator UX

When the operator clicks the Send Button (ChatRequest), TChatSession appends two visuals immediately — before the LLM round-trip begins:

  • An immediate user-echo bubble carrying the operator's typed query, styled with the user-role palette. The operator sees their message land at once instead of staring at an empty panel for 3–10 seconds.

  • A pending row with a rotating ? glyph (one revolution per ~1.2 seconds) and an elapsed-seconds counter that ticks 0s, 1s, 2s, ….

Both visuals are replaced by the authoritative server-emitted bubble pair when the LLM reply lands — no flicker between the echo and the server-snapshot bubble.

Error states — bubbles in the chat track

When the LLM is disabled, unreachable, returns a non-OK envelope, or times out, the platform writes BOTH the user's question AND a paired error-role assistant message into the per-(clientGuid, chatName) transcript cache. The populator renders both as bubbles. The user's question persists; the error text appears as a danger-tinted bubble immediately below it. No separate error band, no toast, no disappearing question — the chat thread is the surface for everything.

Error bubbles use the platform's AlarmHighPriority background token (the canonical alarm-tier red, load-bearing on every shipped theme) with ThemeWhiteBrush foreground for high contrast and DefaultBorder border. Layout, padding, margin, corner radius, max-width, and selection support are identical to user and assistant bubbles — only the palette differs.

Gate state

What the user sees

LLM endpoint unreachable (HTTP error)

User-question bubble + error bubble: "LLM endpoint HTTP error: <detail>".

Master kill-switch off (SolutionCapabilities[LocalAI].Enabled=false)

User-question bubble + error bubble: "Local AI master kill-switch (SolutionCapabilities[LocalAI].Enabled) is off."

Auto-warm failure (Ollama not installed or not running)

User-question bubble + error bubble with actionable install/start guidance.

ModelOptions EnableRuntimeMCP bit (0x02) off

User-question bubble + error bubble naming the disabled bit.

Request wall-clock timeout (60 s budget)

User-question bubble + error bubble: "Chat request timed out."

Info

JSON envelope still available for audit. The Reply JSON tag continues to carry the full envelope (status, text, toolTrace, latencyMs, warnings[]) for adopters who want it for logging, audit, or diagnostic display. The chat surface does NOT depend on JsonString-extracting any envelope field — the platform writes the bubble text directly to the transcript cache, robust across LLM providers because the envelope is FrameworX-emitted, not LLM-emitted.

Cache-write asymmetry, intentional. Error pairs persist to the transcript cache unconditionally, regardless of the ModelOptionsChatHistory bit. Successful turns persist only when that bit is set. The asymmetry is by design — errors are user-actionable signal worth surfacing even when normal chat-history persistence is off.


Role discrimination — tolerant matching

The control declares two role-marker properties:

  • UserRoleValue — default user. Identifies user-role bubbles.

  • AIRoleValue — default assistant. Identifies assistant-role bubbles.

Matching is case-insensitive (OrdinalIgnoreCase) and also tolerates common alias synonyms on each side. A bubble whose Role column matches the declared property OR appears in the role's alias set renders with that role's palette; bubbles whose Role matches neither fall through to the unknown-role branch (neutral palette).

Side

Default property value

Alias set (case-insensitive)

User

user

user, operator, human, question, you, me, customer, client, person, prompt

Assistant

assistant

assistant, ai, bot, agent, response, answer, plant ai, system ai, system, model, copilot, reply

The defaults plus the alias whitelist mean most adopters never need to set UserRoleValue or AIRoleValue explicitly — the runtime writes user and assistant on every row, and both defaults match. Override the properties only when feeding the control from a custom transcript whose role labels do not match the defaults or any alias.

For persona labels visible on the Display (e.g. "Operator", "Plant AI"), add a separate TextBlock above the transcript — do not push the persona text into UserRoleValue / AIRoleValue. The control's contract is to match what the runtime writes; the persona is a Display-level affordance.


Multiple chat sessions on one Display

A Display panel may carry several TChatSession controls — for example, a primary operator chat plus a side-panel diagnostic chat against a different model. Each control's transcript cache is keyed by its Name property, so distinct instances on the same Display address distinct cache entries automatically with no author wiring.

When you wire the ChatRequest Action and want it to refresh a specific TChatSession (rather than refreshing every TChatSession on the panel), set the Action's optional ChatSessionUid field to the target control's Uid. Empty ChatSessionUid falls back to enumerating every TChatSession descendant of the Display — the correct default for single-session panels.


Cross-target — WPF and HTML5

TChatSession is shared source — the same control compiles into the WPF Rich Client (.NET 4.8) and into the HTML5 Web Client (OpenSilver / WASM). Author wiring does NOT differ between the two targets. Visual parity holds for the full layout, the color palette, the auto-scroll, the auto-size height, and the pending-indicator. Selection + Ctrl-C copy is active today on the WPF target; on the HTML5 target it degrades gracefully — no error, just no selection — until the underlying OpenSilver TextBlock surfaces the relevant property.


Lifecycle actions

TChatSession is a rendering control. The three Display Actions below operate on the per-Display-panel transcript that TChatSession displays. Attach them to Buttons on the same Display panel for a complete operator chat surface.

Action

What it does

ChatRequest Action Reference

Sends the operator's query to the LLM, maintains the per-Display-panel transcript across turns, dispatches platform tools the model may request, refreshes the TChatSession surface on reply landing. The primary action for an operator chat panel.

ChatClear Action Reference

Wipes the transcript for the addressed chat session immediately, without calling the LLM. Use for "Start new conversation" buttons and shift-handover resets. Synchronous and idempotent.

ChatCompress Action Reference

Summarises the current transcript via one LLM call and atomically replaces it with the summary. Preserves semantic continuity while reducing token cost on long conversations. Asynchronous; takes 3–10 seconds on a local model.


Properties

Property set auto-extracted from ControlSchemas.json (build fx-10.1.5.2000, schema 1.0, generated 2026-05-17T21:29:29.5050227Z).

Property

Type

Default

Description

Left

Double

0

X position from left edge (unit: pixels)

Top

Double

0

Y position from top edge (unit: pixels)

Width

Double

100

Element width (unit: pixels). Cleared to auto-size on Loaded.

Height

Double

100

Element height (unit: pixels). Cleared to auto-size on Loaded.

AutoScrollToBottom

Boolean

(none)

true

When true, the inner viewport scrolls to the newest bubble on every transcript update. Recommended for live chat. Set false when reviewing history.(no description in schema)

UserRoleValue

String

(none)

user

String the control treats as the user-role marker. Case-insensitive + alias whitelist (see "Role discrimination" above).(no description in schema)

AIRoleValue

String

(none)

assistant

String the control treats as the assistant-role marker. Case-insensitive + alias whitelist (see "Role discrimination" above).(no description in schema)

BubbleCornerRadius

Double

(none)

(no description in schema)

DesignQuantity

Integer

(none)

(no description in schema)

PreviewQuantity

Integer

(none)

(no description in schema)

DesignElements

String

(none)

(no description in schema)

PreviewElements

String

(none)

(no description in schema)

PreviewMargin

String

(none)

(no description in schema)

DesignSingleType

Boolean

(none)

(no description in schema)

PreviewSingleType

Boolean

(none)

(no description in schema)

PreviewSettings

String

(none)

(no description in schema)

DesignWidth

Double

100

(no description in schema)

PreviewWidth

Double

(none)

(no description in schema)

DesignHeight

Double

100

(no description in schema)

PreviewHeight

Double

(none)

(no description in schema)

DesignMargin

String

5

(no description in schema)

DesignSettings

String

(none)

(no description in schema)

MaxItemsLink

String

(none)

(no description in schema)

ItemsSourceOption

Enum

0

Data source type: Designer (static list), ArrayTag (tag array), DataTable

ItemsSourceType

Enum

(none)

Source kind: Text (static list via ItemsList), ArrayTag (array tag values), DataTable (Dataset Query or Table — FK pattern). For FK dropdowns use DataTable + ItemsSourceLink='@Dataset.Query.X' + DisplayMemberPath + SelectedValuePath.

ItemsSourceLink

String

(none)

Source for populating list items. Interpretation depends on ItemsSourceType: Text → @Tag.OptionsList (array or CSV tag) ArrayTag → @Tag.ArrayOfStrings DataTable → @Dataset.Query.NameOfQuery (RECOMMENDED for FK dropdowns) In DataTable mode the ComboBox auto-fires the backing query at display-open — no script Select() needed.

ReloadItemsLink

String

(none)

Tag that triggers list refresh when its value changes

ContainerPanel

Enum

0

(no description in schema)

14

Corner rounding of each message bubble, in pixels. Applies uniformly to user and assistant bubbles.

ItemsSourceLink

String

(empty)

Advanced. When empty, the control auto-resolves to the live server-side transcript for the current client (recommended). When set to a custom DataTable Tag reference (e.g. @Tag.MyDataTable), the control reads from that Tag instead — the bring-your-own-transcript escape hatch (see below).

ItemsSourceOption

Enum

DataTable

Pinned to DataTable by the control's ctor. Authors do not change this.

Background

Color

(themed)

Background color of the control's outer chrome

Background

Color

(none)

Background color (#AARRGGBB). Themed by default — OMIT to use theme.

Foreground

Color

(nonethemed)

TextDefault text/foreground color of the outer chrome (#AARRGGBB). Themed by default — OMIT to use theme. Note: bubble foreground is driven by the per-role palette and is NOT controlled by this property.

BorderBrush

Color

(nonethemed)

Border Outer border color (#AARRGGBB).

BorderThickness

String

(nonethemed)

Border Outer border thickness (single value or 'left,top,right,bottom').

ChatSession-specific properties

The auto-generated table above ships with empty descriptions for several ChatSession-specific properties. Until the next schema regeneration carries the descriptions through, use the editorial notes below.

Property

Description

AutoScrollToBottom

When true, the viewport scrolls to the newest message as soon as the bound collection grows. Recommended for live operator chat panes so a new AI reply is visible without user interaction. Set to false when reviewing historical transcripts where the user expects the scroll position to be preserved.

UserRoleValue

The string the control treats as the user role marker. Each item in the bound collection whose role field equals this value is rendered as a user bubble (right-aligned by default). May be a literal (e.g. user) or a tag-bound expression. Must match exactly what the Script writes when appending user messages.

AIRoleValue

The string the control treats as the AI role marker. Items whose role field equals this value render as AI bubbles (left-aligned by default). May be a literal (e.g. assistant) or a tag-bound expression. Items whose role matches neither marker fall back to the default bubble style.

BubbleCornerRadius

Corner rounding of each message bubble, in pixels. 0 renders square bubbles; higher values produce a more conversational, mobile-style appearance. Applies uniformly to user and AI bubbles.

Additional Properties

The properties below also ship with empty descriptions in the auto-generated table. They configure Designer-time and Preview-mode rendering of sample items inside the ChatSession surface. Behaviors are conservative best-effort from the schema shape; consult ControlSchemas.json for the current default value.

Property

Description

DesignQuantity

Number of sample items rendered in the Designer canvas when no live source is bound. Used so the control occupies meaningful space while the Display is being authored.

PreviewQuantity

Number of sample items rendered in Preview mode. Lets the author validate scrolling and bubble layout against a representative item count before going live.

DesignElements

Comma- or newline-separated sample items rendered inside the control at design time. Each entry produces one preview bubble. Use to visualize the bubble styling without binding a source.

PreviewElements

Same shape as DesignElements but rendered while the Display is in Preview mode. Lets the author drive the live rendering path with a known sample set.

PreviewMargin

Outer spacing around preview items, in pixels. Single value applies uniformly; left,top,right,bottom applies per side. Controls how preview items pack inside the ChatSession frame.

DesignSingleType

When true, restricts the Designer preview to a single role — user OR AI — so the author can validate one bubble style in isolation. When false, design preview alternates roles.

PreviewSingleType

Same as DesignSingleType but applied in Preview mode. Useful when the live source is mocked with a single-role sample.

PreviewSettings

Serialized render settings applied to Preview-mode items (typography, color overrides, spacing). Edited through the Designer property editor rather than by hand; consult ControlSchemas.json for the current default value.

PreviewWidth

Width of the preview frame within the control, in pixels. Controls how wide each preview bubble may stretch before wrapping. Defaults to the auto-generated design-mode width when unset.

PreviewHeight

Height of the preview frame within the control, in pixels. Combined with PreviewQuantity determines whether preview content scrolls.

DesignSettings

Serialized render settings applied to Designer-canvas items (counterpart to PreviewSettings). Controls typography, colors, and spacing while the Display is being authored. Edited through the Designer property editor; consult ControlSchemas.json for the current default value.

MaxItemsLink

Tag expression that caps the maximum number of items the control will render from the bound source. When unset, the full bound collection is rendered. Use for live operator chat panes where the visible history must be bounded to keep the bubble list responsive.

MaxItemsLink

String

100 at fresh-drop

Caps the maximum number of bubbles the control renders. Useful for very long transcripts where the visible history must be bounded. Fresh-drop default is 100; existing Displays preserve whatever the .dbsln carries.

Inherited properties not authored on this control

The control inherits a Designer-canvas / preview-mode sample-rendering surface from its parent class (DesignQuantity, PreviewQuantity, DesignElements, PreviewElements, PreviewMargin, DesignSingleType, PreviewSingleType, PreviewSettings, DesignWidth, PreviewWidth, DesignHeight, PreviewHeight, DesignMargin, DesignSettings, ReloadItemsLink, ContainerPanel). These properties are not authored on TChatSession — they describe a generic list-of-elements panel surface, not a chat session whose container shape and data source are pinned by the control itself. The Designer property panel suppresses them by default.


Advanced — bring-your-own transcript

The zero-substrate path is the recommended pattern for ~95 % of chat surfaces. The bring-your-own-transcript escape hatch exists for the remaining cases — a frozen archive Display, a filtered conversation view, a cross-solution merge.

Set ItemsSourceLink to a DataTable Tag reference (e.g. @Tag.MyDataTable). The control bypasses the zero-substrate auto-resolve and reads from that Tag instead. The DataTable schema must contain at minimum:

  • An Element column carrying the fully-qualified element type name (e.g. T.Wpf.RunControls.TTextBlock) — identifies the per-row bubble shape.

  • A LinkedValue column carrying the message text (each cell is the bubble's content).

  • A Role column carrying the role string — user, assistant, or any value in the alias whitelist.

When the DataTable updates (rows added, rows removed, contents changed), bind ReloadItemsLink to a pulse tag so the control re-reads on demand.

Adopters using a custom DataTable Tag continue to work unchanged against the zero-substrate ship — the escape hatch is purely additive.


See also

Related actions

ChatSession is a rendering control. The Display Actions listed below operate on the server-side transcript that ChatSession displays. Attach them to Buttons on the same Display panel to give operators full control of the conversation lifecycle.

Action

What it does

ChatRequest Action Reference

Sends the operator’s query to the LLM, manages the per-panel transcript across turns, and dispatches platform tools the model may request. The primary action for an operator chat panel.

ChatClear Action Reference

Wipes the transcript for the addressed chat session immediately, without calling the LLM. Use for “Start new conversation” buttons and shift-handover resets.

ChatCompress Action Reference

Summarises the current transcript via one LLM call and atomically replaces it with the summary. Preserves semantic continuity while reducing token cost on long conversations
  • .


In this section...

Page Tree
root@parent