PupauChatController class

Inheritance
  • Object
  • GetLifeCycle
  • DisposableInterface
  • GetxController
  • PupauChatController
Implemented types

Constructors

PupauChatController({PupauConfig? config})

Properties

activeToolLoadings → RxMap<String, ToolUseType>
Active tool loadings keyed by tool name. This allows multiple tools (pending or running) to be shown simultaneously. Reactive so that isLoadingMessageActive and any Obx that reads it rebuilds automatically whenever a tool is added or removed.
final
alwaysMemoriesBackup List<MemoryAlways>
getter/setter pair
assistant ↔ Rxn<Assistant>
getter/setter pair
assistantId String
no setter
assistants List<Assistant>
getter/setter pair
assistantsReplying ↔ RxInt
getter/setter pair
attachmentToolLoadingLabels → RxMap<String, String>
Rich loading label for the JIT attachment tools (list_attachments, attachment_outline, attachment_read, attachment_grep, attachment_search), derived from TOOL_USE_START's typeDetails.toolArgs (e.g. "Reading report.pdf (lines 1-200)"). Keyed by tool name, same as activeToolLoadings. Falls back to a generic per-tool label when args aren't known yet (TOOL_PENDING).
final
attachmentTrimmingOpenedMessageIds ↔ RxSet<String>
Message IDs for which the attachment trimming modal was opened at least once (persisted in prefs).
getter/setter pair
autoScrollEnabled bool
Transient runtime state: whether auto-scroll is currently allowed. This is NOT a preference. It's suspended by any user manual scroll, and re-enabled automatically when the user returns to bottom AND the magnet preference is enabled.
getter/setter pair
autoScrollMagnetEnabled → RxBool
User preference for "magnetic" auto-scroll to bottom. Default is disabled (open lock) and only changes on explicit user tap.
final
autoScrollSuspendedByUser bool
Sticky runtime state: once the user manually scrolls, keep auto-scroll suspended until the user explicitly returns to bottom (or taps the arrow). Programmatic scrolls to bottom must NOT clear this.
getter/setter pair
cachedToolUseImages Map<String, Uint8List>
getter/setter pair
chatExtraBottomPaddingActive → RxBool
Extra scroll slack under the thread (MessagesList). Set true only when the user sends a message in this controller instance; cleared when the chat/conversation resets.
final
chatScrollController ScrollController
getter/setter pair
chatShellNavigatorKey GlobalKey<NavigatorState>
In-view navigator for sized/floating chat; used to push the dashboard route.
final
conversation ↔ Rxn<PupauConversation>
getter/setter pair
conversationActiveSkills → RxMap<String, SkillLoadedInfo>
Skills currently active in this conversation (SSE + latest history snapshot).
final
conversationItemsLoaded int
getter/setter pair
conversationPage int
getter/setter pair
conversationSseSubscription StreamSubscription<SSEModel>?
getter/setter pair
conversationStarters ↔ RxList<String>
getter/setter pair
currentWebSearchType ↔ Rxn<WebSearchType>
getter/setter pair
editMessageTextController TextEditingController
Shared with showEditMessageModal; disposed in onClose only.
getter/setter pair
effectiveWelcomeMessage String
Welcome message to show: from assistant once loaded, otherwise from pupauConfig.initialWelcomeMessage if provided (e.g. by host from list).
no setter
expandedLoadingTools → RxSet<String>
final
expandedMessageGroupIds → RxList<String>
GroupIds (trimmed) whose message group is expanded in the messages list.
final
expandedToolUseMessages ↔ RxSet<String>
getter/setter pair
externalSearchVisible ↔ RxBool
getter/setter pair
filteredAssistants ↔ RxList<Assistant>
getter/setter pair
forkConversationTitle ↔ RxString
getter/setter pair
forkConversationTitleController TextEditingController
getter/setter pair
forkMessageId ↔ RxString
getter/setter pair
groundingSourcesBackup List<GroundingSource>
getter/setter pair
hasApiError ↔ RxBool
getter/setter pair
hashCode int
The hash code for this object.
no setterinherited
hasListeners bool
no setterinherited
hiddenUiToolMessages ↔ RxSet<String>
getter/setter pair
hideAudioRecordingButton bool
no setter
hideInputBox ↔ RxBool
getter/setter pair
incomingMessages List<PupauMessage>
getter/setter pair
initialized bool
Checks whether the controller has already been initialized.
no setterinherited
inputMessage ↔ RxString
getter/setter pair
inputMessageController MyMentionTagTextEditingController
getter/setter pair
isActionBarAlwaysVisible ↔ RxBool
getter/setter pair
isAnonymous bool
no setter
isAtBottom ↔ RxBool
getter/setter pair
isAttachmentAvailable ↔ RxBool
getter/setter pair
isAtTop ↔ RxBool
getter/setter pair
isChatEntryResolving ↔ RxBool
True until the first openChatWithConfiginitChatController pass finishes (_signalFirstInitComplete). Also set true at each chat open so the UI never flashes EmptyConversationView before we know real empty vs loading history.
getter/setter pair
isClosed bool
Checks whether the controller has already been closed.
no setterinherited
isConversationHistoryLoaded bool
getter/setter pair
isConversationLastPage bool
getter/setter pair
isDashboardAvailable ↔ RxBool
getter/setter pair
isEmbeddedChatDashboardOpen → RxBool
Tracks an in-shell dashboard route (sized/floating) for PopScope.canPop. The nested Navigator does not notify Obx when its stack changes.
final
isForking ↔ RxBool
getter/setter pair
isLiveVoiceAvailable bool
no setter
isLoadingAssistant ↔ RxBool
getter/setter pair
isLoadingConversation ↔ RxBool
getter/setter pair
isLoadingConversationPage bool
getter/setter pair
isLoadingTitle ↔ RxBool
getter/setter pair
isMarketplace bool
no setter
isMentionAvailable ↔ RxBool
getter/setter pair
isMessageInputFieldFocused ↔ RxBool
getter/setter pair
isRecording ↔ RxBool
getter/setter pair
isStopping ↔ RxBool
True while sendCancel is awaiting the backend stop acknowledgement. While true the stop and send buttons are disabled and the stop button shows a stacked CircularProgressIndicator over the stop icon.
getter/setter pair
isStreaming ↔ RxBool
getter/setter pair
isVoiceDetected ↔ RxBool
getter/setter pair
isVoiceMode ↔ RxBool
getter/setter pair
isVoicePlaying ↔ RxBool
getter/setter pair
isWebSearchActive ↔ RxBool
getter/setter pair
isWebSearchAvailable ↔ RxBool
getter/setter pair
kbReferencesBackup List<KbReference>
getter/setter pair
keyboardFocusNode FocusNode
final
latestQueryAssistantClusterHeight → RxDouble
Laid-out height of the latest query's assistant cluster (see HeightReportingContainer). Reduces fixed bottom slack in MessagesList while chatExtraBottomPaddingActive.
final
listeners int
no setterinherited
listHeight double
getter/setter pair
loadingMessage ↔ Rx<LoadingMessage>
Global loading state (dots, text, web search, or tool-use). For tools, this can represent multiple concurrent tool loadings.
getter/setter pair
loadingToolsTick → RxInt
final
memoryReferencesBackup List<MemoryReference>
getter/setter pair
mentionValue ↔ RxString
getter/setter pair
messageGroupExpandEpoch → RxInt
Bumped on expand/collapse so Obx listeners rebuild when set size is unchanged.
final
messageInputFieldHeight ↔ RxDouble
getter/setter pair
messageNotifier MessageNotifier
getter/setter pair
messages ↔ RxList<PupauMessage>
getter/setter pair
messageSendStream StreamSubscription?
getter/setter pair
onDelete → InternalFinalCallback<void>
Internal callback that starts the cycle of this controller.
finalinherited
onStart → InternalFinalCallback<void>
Called at the exact moment the widget is allocated in memory. It uses an internal "callable" type, to avoid any @overrides in subclases. This method should be internal and is required to define the lifetime cycle of the subclass.
finalinherited
pendingScrollAlignUserMessageId → Rx<String?>
When set, MessageWithOptionalDateHeader attaches scrollAlignSentUserBubbleKey to that message for one-shot alignment after send.
final
pupauConfig PupauConfig?
getter/setter pair
recordingDuration ↔ Rx<Duration>
getter/setter pair
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
safeContext BuildContext?
no setter
scaffoldContext BuildContext?
no setter
scrollAlignSentUserBubbleKey GlobalKey<State<StatefulWidget>>
Scroll slack below the message list so Scrollable.ensureVisible can move the latest user bubble toward the top of the viewport (see scheduleSentUserBubbleAlign).
final
selectedImage ↔ Rxn<ChatImage>
getter/setter pair
showNerdStats ↔ RxBool
getter/setter pair
taggedAssistants ↔ RxList<Assistant>
getter/setter pair
thinkingEffort ↔ RxString
getter/setter pair
thinkingEnabled ↔ RxBool
getter/setter pair
toolArgsPreviewContentsById → RxMap<String, String>
final
toolArgsPreviewTitlesById → RxMap<String, String>
final
toolArgsPreviewToolIdByName → RxMap<String, String>
final
toolPartialStatuses → RxMap<String, String>
Optional per-tool status label for tools that emit TOOL_PARTIAL_RESULT, e.g. document_create/document_update phases. Reactive so that the loading animation label updates live.
final
toolsFabExpanded ↔ RxBool
getter/setter pair
ttsService TtsService
getter/setter pair
userToggledLoadingTools → RxSet<String>
final
userToggledToolUseMessages ↔ RxList<String>
getter/setter pair
voiceAmplitude ↔ RxDouble
getter/setter pair
voiceSilenceProgress ↔ RxDouble
getter/setter pair
widgetMode WidgetMode
no setter

Methods

$configureLifeCycle() → void
inherited
addGroundingSourcesBackupToMessage(PupauMessage message) → void
addKbBackupToMessage(PupauMessage message) → void
addListener(GetStateUpdate listener) → Disposer
Register a closure to be called when the object notifies its listeners.
inherited
addListenerId(Object? key, GetStateUpdate listener) → Disposer
inherited
addMemoryBackupToMessage(PupauMessage message) → void
addMessage(PupauMessage message, {bool bypassCheck = false}) → void
addTaggedAssistants() → void
applyCachedAssistantIfAvailable() → void
Applies the assistant from PupauAssistantsController cache if present for the current pupauConfig assistantId. Synchronous, no network. Use so the UI shows the correct agent immediately when opening or switching chat, before getAssistant returns.
applyGroundingVerification(GroundingVerificationFrame frame) → void
Applies a verification result (§3.1/§3.3) — either the live grounding_verification frame or the reconnect catch-up grounding_verified event, both funneled through the same GroundingVerificationFrame shape. Idempotent / last-write-wins, keyed on queryId, and also propagated to any sibling rows in the same queryGroupId that already share this turn's grounding.
assignStreamingGroup(PupauMessage userMessage) → void
cancelRecording() Future<void>
canRetryAudioMessage(PupauMessage message) bool
clearAutoScrollSuspension() → void
Clears the user suspension so magnet can resume when at bottom.
clearEmptyMessages() → void
clearTaggedAssistants() → void
clearToolArgsPreviewCache() → void
closeDrawer() → void
Safely closes the drawer using scaffoldKey or context
closeEndDrawer() → void
Safely closes the end drawer using scaffoldKey or context
createNewConversation() Future<void>
dispose() → void
inherited
disposeId(Object id) → void
To dispose an id from future updates(), this ids are registered by GetBuilder() or similar, so is a way to unlink the state change with the Widget from the Controller.
inherited
editUserMessage(PupauMessage message, String newText) Future<void>
Fork after the previous user query (or new conversation if this was the first user message), then send newText.
exitVoiceModeIfActive() → void
Called by the chat widget when it is removed from the tree (deactivate), covering all close paths: back nav, sized-mode collapse, floating-mode close.
forkConversation() Future<void>
getAssistant() Future<void>
getAttachmentToolLoadingLabel(String toolName) String?
Rich label for an active attachment tool loading bubble, or null if not known yet (falls back to AttachmentToolLabelService.genericLabel).
getMessageInputFieldHeight(BuildContext? context) → void
getThinkingEffortSettings() → void
getToolArgsPreviewContentByToolId(String toolId) String
getToolArgsPreviewTitleByToolId(String toolId) String
getToolLoadingSeconds(String toolName) int
handleAttachmentTrimmingEvent(Map<String, dynamic> data) → void
handleAudioInputTranscription(PupauMessage newSseMessage) → void
handleKbMessage(PupauMessage message) → void
handleLayerMessage(PupauMessage message) → void
handleMemoryMessage(PupauMessage message) → void
handleSkillSseEvent(PupauMessage message) → void
handleToolArgsDeltaEvent(Map<String, dynamic> data) → void
handleToolEvaluationMessage() → void
TOOL_EVALUATION means all tools of the current stream have been resolved. Clear any remaining tool loadings.
handleToolHeartbeatEvent(Map<String, dynamic> data) → void
handleToolPartialResultEvent(Map<String, dynamic> data) → void
Handle TOOL_PARTIAL_RESULT events for tools that emit intermediate phases (currently document_create/document_update).
handleToolUseCompletionByMessage(PupauMessage message) → void
Remove a single tool from the active loading map based on message.toolName.
handleToolUseMessage(Map<String, dynamic> data) → void
handleToolUseStartPendingMessage(PupauMessage message, Map<String, dynamic> data) → void
handleUiToolMessage(Map<String, dynamic> data) → void
handleWebSearchQueryMessage(PupauMessage message) → void
hasToolArgsPreview(String toolName) bool
hasToolArgsPreviewByToolId(String toolId) bool
hideUiToolBubble(String messageId) → void
initChatController() Future<void>
initLanguage() → void
initScrollControllers() → void
isAdvanced() bool
isFirstMessageInGroup(String groupId) bool
isLoadingMessageActive() bool
isLoadingToolExpanded(String toolName, {ToolUseType? toolUseType}) bool
isMessageGroupExpanded(String groupId) bool
isThinkingSupported() bool
isToolUseExpanded(String messageId) bool
isUiToolBubbleHidden(String messageId) bool
loadConversation(String conversationId) Future<void>
loadConversationMessages({bool reset = false}) Future<void>
manageCancelAndErrorMessage() → void
manageChatAutoScroll() → void
manageForceBack() → void
manageMessageContextMenu(int selectedOption, PupauMessage message) → void
manageNoVisionCapability() → void
manageSendSuccess(bool isExternalSearch) → void
manageSSEData(Map<String, dynamic> data, bool isExternalSearch) → void
markToolLoadingEnded(String toolName) → void
markToolLoadingStarted(String toolName) → void
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
notifyChildrens() → void
inherited
onClose() → void
Called before onDelete method. onClose might be used to dispose resources used by the controller. Like closing events, or streams before the controller is destroyed. Or dispose objects that can potentially create some memory leaks, like TextEditingControllers, AnimationControllers. Might be useful as well to persist some data on disk.
override
onInit() → void
Called immediately after the widget is allocated in memory. You might use this to initialize something for the controller.
override
onMention(String? value) → void
onMentionTap() → void
onReady() → void
Called 1 frame after onInit(). It is the perfect place to enter navigation events, like snackbar, dialogs, or a new route, or async request.
override
openChatDashboard() → void
openChatWithConfig(PupauConfig? newConfig) Future<void>
Called when chat is opened (via PupauChatUtils or tapping avatar) Resets conversation state and updates config if assistant changed Re-initializes the chat every time it's called (even with same config)
openCustomActionsModal() → void
openDrawer() → void
Safely opens the drawer using scaffoldKey or context
openEndDrawer() → void
Safely opens the end drawer using scaffoldKey or context
openForkConversationModal(String messageId) → void
reactMessage(PupauMessage message, Reaction reaction) → void
rebuildConversationSkillsFromHistory() → void
refresh() → void
inherited
refreshGroup(Object id) → void
inherited
reloadCurrentAssistant() Future<void>
Reloads the current assistant from the API using pupauConfig. Use this when config (e.g. assistantId or API settings) has changed and the UI should reflect the latest assistant data without reopening the chat.
removeListener(VoidCallback listener) → void
Remove a previously registered closure from the list of closures that the object notifies.
inherited
removeListenerId(Object id, VoidCallback listener) → void
inherited
removeTaggedAssistant(Assistant assistant) → void
reportMessage(PupauMessage message) → void
resetChatState({required bool clearConversationStarters}) → void
Resets all chat state when the chat is opened This ensures a fresh state each time the chat is opened
resetConversation() → void
resetConversationPagination() → void
resetExtraBottomScrollPadding() → void
Clears chatExtraBottomPaddingActive when switching conversations / resetting chat.
resetLoadingMessage() → void
retryLastFailedAudioMessage() Future<void>
scrollToBottomChat({bool withAnimation = false, double minDistance = 0.0}) → void
Scrolls the chat list to the bottom (maxScrollExtent).
scrollToTopChat({bool withAnimation = false}) → void
scrollToUserMessage(String messageId) → void
selectImage(String value, ImageType type) → void
sendAudioMessage(File audioFile, {bool isVoiceMode = false}) Future<void>
sendCancel() Future<void>
Sends a stop request to the backend and waits for confirmation before finalizing the cancel locally.
sendIsActive() bool
sendMessage(String query, bool isExternalSearch) Future<void>
sendToolAnswer(String messageId, List<AskUserChoice> selectedOptions, String? answer) Future<void>
sendUiToolApproval(String messageId) Future<void>
sendUiToolAuth(String messageId, String toolId) Future<void>
setAssistantSettings() Future<void>
setCollapseCallback(VoidCallback? callback) → void
setDefaultMessageInputFieldHeight() → void
setExternalSearchButton(bool isVisible) → void
setForkConversationTitle(String title) → void
setLastEventId(SSEModel event) → void
setLatestQueryAssistantClusterHeight(double heightPx) → void
Updates measured assistant cluster height for dynamic bottom slack (MessagesList).
setMessageInputFieldFocused(bool isFocused) → void
setModalContext(BuildContext context) → void
setNerdStats(bool value) → void
setOnFirstInitCompleteCallback(VoidCallback? callback) → void
setScaffoldContext(BuildContext context) → void
setThinkingEffort(String? effort) Future<void>
setThinkingEnabled(bool enabled) Future<void>
showAttachmentTrimmingModalForMessage(PupauMessage message) → void
Shows the attachment/emergency trimming modal for an assistant message and marks it as opened.
startListeningNow() Future<void>
Restart listening from idle (e.g. after the user taps PTT in idle phase).
startRecording() Future<void>
stopActiveStreams() → void
Stops any active SSE streams so the UI no longer receives updates.
stopAndSendRecording() Future<void>
stopAudioPlayback() → void
Stops audio playback mid-sentence and resumes listening so the user can speak again without waiting for the AI to finish talking.
stopExecution() Future<bool>
Stops the server-side async run for the current conversation (if any).
stopIsActive() bool
submitVoiceNow() Future<void>
Immediately submit the current voice recording (bypasses VAD silence wait).
supportedThinkingEfforts() List<String>
suspendAutoScroll() → void
Suspends auto-scroll without changing the magnet preference.
syncLoadingMessageFromActiveTools() → void
Update loadingMessage from activeToolLoadings, supporting multiple concurrent tool loadings.
thinkingEffortToSend() String?
Returns the effort to send (validated) or null. Only meaningful when thinkingEnabled is true and model supports it.
toggleAutoScrollMagnet() → void
toggleLoadingToolExpanded(String toolName) → void
toggleMessageGroupExpanded(String groupId) → void
toggleToolsFab({bool? value}) → void
toggleToolUseExpanded(String messageId) → void
toggleVoiceMode() → void
toggleWebSearch() → void
toString() String
A string representation of this object.
inherited
tryCloseEmbeddedChatDashboard() bool
When sized/floating, pops the in-shell dashboard route if it is on top. Returns true if a nested route was popped.
update([List<Object>? ids, bool condition = true]) → void
Rebuilds GetBuilder each time you call update(); Can take a List of ids, that will only update the matching GetBuilder( id: ), ids can be reused among GetBuilders like group tags. The update will only notify the Widgets, if condition is true.
inherited
updateConversationTitle(String title) → void
updateSSEMessages(PupauMessage newSseMessage) PupauMessage

Operators

operator ==(Object other) bool
The equality operator.
inherited