Use AfterAgentTurn.
The same emitter under the old binding name, so a template still binding (afterAgentTurn) keeps working. Must stay AFTER AfterAgentTurn: class fields initialise in order, and the other way round this captures undefined.
Fired AFTER a successful agent turn, on every route. Carries the agent run id and the full agent result. Not fired when BeforeAgentTurn was canceled, when the turn failed, or when a host AgentTurnHandler reported no result.
The MJ: AI Agent Configurations.ID selected via the chat header's
mode picker (Draft / Standard / High). Applied to non-mention
routes — when the user types without @mention, this preset rides
along on the next invokeSubAgent call so the server resolves the
agent's Fast / Standard / High Power AI configuration accordingly.
Mentioned-route turns still use the preset embedded in the mention
(e.g. @Form Builder /high) because that's a per-message intent
the user just expressed. Continuity-route turns (last responder
agent) also honor this input as the fallback when the prior
message itself doesn't carry an explicit configuration preset.
Picker writes are forward-only: changing the mode does NOT re-route messages already in flight or already in history. Affects "what happens next."
The first moment of the conversation an agent turn may read. The server loads the agent's history from there and uses no summary of earlier messages; the run's own reads of the conversation (history tools, attached artifacts, the previous output it continues from) start there too, and so does the continuity route, which considers only replies written at or after it. Sent to the server only when set, so leaving it null keeps working against an MJAPI that predates it (one that predates it rejects a turn that sets it, rather than reading past the floor). Null (the default) reads the whole conversation.
When a message starts an agent turn. 'Always' (the default) answers every message, as
before. 'MentionOnly' answers only a message that tags an agent; any other message is
posted with no turn at all — no reply row, no placeholder, no turn events — which is what a
chat between several people needs.
Use AgentResponse.
The same emitter under the old binding name, so a template still binding (agentResponse) keeps working. Must stay AFTER AgentResponse: class fields initialise in order, and the other way round this captures undefined.
Use AgentRunDetected.
The same emitter under the old binding name, so a template still binding (agentRunDetected) keeps working. Must stay AFTER AgentRunDetected: class fields initialise in order, and the other way round this captures undefined.
OptionalAgentUse AgentRunUpdate.
The same emitter under the old binding name, so a template still binding (agentRunUpdate) keeps working. Must stay AFTER AgentRunUpdate: class fields initialise in order, and the other way round this captures undefined.
Runs agent turns on the host's server instead of MJ's own path. The chat area still picks the agent and fires BeforeAgentTurn; it then calls the handler once per turn, before any reply row exists, and shows the rows the handler reports. Null (the default) runs turns on MJ's path.
The agents that may answer here. Narrows the composer's '@' list, every route (a tagged agent, continuity, the pinned and host default agents, the conversation manager) and the conversation manager's delegation, including each agent step of a workflow it plans. A tagged agent outside the list is ignored. Null (the default) allows every agent the user can run; an empty list allows none.
Application context for the current conversation. Threaded through from the chat-area component for inclusion in the beforeAgentTurn event payload — lets listeners reason about which app's chat surface is invoking the agent. Optional; defaults to null for surfaces with no app context.
Use ArtifactCreated.
The same emitter under the old binding name, so a template still binding (artifactCreated) keeps working. Must stay AFTER ArtifactCreated: class fields initialise in order, and the other way round this captures undefined.
OptionalArtifactsWhether MJ names a new conversation from its first message. True (the default) keeps today's behavior; a host that names its own chats turns it off.
Use BeforeAgentTurn.
The same emitter under the old binding name, so a template still binding (beforeAgentTurn) keeps working. Must stay AFTER BeforeAgentTurn: class fields initialise in order, and the other way round this captures undefined.
Cancelable — fired once per agent turn, on every route, after routing has picked the agent
and BEFORE any reply row exists. Listeners may set event.Cancel = true to stop the turn
(nothing more is written, and AfterAgentTurn does not fire) or set
event.RedirectAgentId to send it to another allowed agent. A message that starts no turn
fires nothing. Follows MJ's established Before/After cancelable event pattern.
The composer lost focus — hosts flush persisted drafts on this.
Per-conversation pinned default agent — sourced from the loaded
MJConversationEntity.DefaultAgentID. When set, this agent is used in
preference to the embedder-supplied defaultAgentId so a user
who pins a conversation to e.g. Research Agent gets that routing even
inside an embedded surface whose embedder defaults to a different
specialist. Routing precedence:
1.
OptionalConversationUse ConversationRenamed.
The same emitter under the old binding name, so a template still binding (conversationRenamed) keeps working. Must stay AFTER ConversationRenamed: class fields initialise in order, and the other way round this captures undefined.
Optional default agent ID for the conversation. When set, the FIRST message routes directly to this agent — skipping Sage's default delegation — provided the user did not
a different agent and there is no prior agent in the conversation history. After the first message, the existing "last non-Sage agent" continuity rule keeps subsequent messages on the same agent.
Used by embedded chat surfaces (Form Builder cockpit, future domain-specific chats) that have an obvious specialist agent for the context and don't need Sage to route. Leave unset to preserve the standard Sage-fronted UX of the main Chat app.
Live draft-state signal: fires on every composer value change with the SERIALIZED content (mention pills encoded via getPlainTextWithJsonMentions, so hosts can persist drafts losslessly). Empty string = draft cleared.
Use EmptyStateSubmit.
The same emitter under the old binding name, so a template still binding (emptyStateSubmit) keeps working. Must stay AFTER EmptyStateSubmit: class fields initialise in order, and the other way round this captures undefined.
Whether an unmentioned message asks one typed decision which agent in the conversation should
answer it, instead of always going back to the last agent that answered. The same call can
name the artifact version the message modifies. The answer replaces continuity only when it
is confident and arrives in time; an error, a slow or unsure answer keeps today's routing, and
a tagged message or a form response makes no call (see decision-routing.ts). False (the
default) changes nothing: no call, and today's routing.
What goes to the model: each qualifying message sends these to the model behind the
Default Decision prompt, which can be a different vendor from the agents' own: the first
1,000 characters of the new message, the last 6 turns (150 characters each), each participant's
name, description and last reply, and the names of their artifact versions. Each call writes an
MJ: AI Prompt Runs row, even when the answer comes too late to be used.
Use InitialDraftApplied.
The same emitter under the old binding name, so a template still binding (initialDraftApplied) keeps working. Must stay AFTER InitialDraftApplied: class fields initialise in order, and the other way round this captures undefined.
Use InitialMessageAutoSendFailed.
The same emitter under the old binding name, so a template still binding (initialMessageAutoSendFailed) keeps working. Must stay AFTER InitialMessageAutoSendFailed: class fields initialise in order, and the other way round this captures undefined.
Use InitialMessageAutoSendStarted.
The same emitter under the old binding name, so a template still binding (initialMessageAutoSendStarted) keeps working. Must stay AFTER InitialMessageAutoSendStarted: class fields initialise in order, and the other way round this captures undefined.
Use IntentCheckCompleted.
The same emitter under the old binding name, so a template still binding (intentCheckCompleted) keeps working. Must stay AFTER IntentCheckCompleted: class fields initialise in order, and the other way round this captures undefined.
Use IntentCheckStarted.
The same emitter under the old binding name, so a template still binding (intentCheckStarted) keeps working. Must stay AFTER IntentCheckStarted: class fields initialise in order, and the other way round this captures undefined.
The people the composer's '@' list offers, such as the chat's members. Null (the default) offers only the current user, as before.
Use MessageComplete.
The same emitter under the old binding name, so a template still binding (messageComplete) keeps working. Must stay AFTER MessageComplete: class fields initialise in order, and the other way round this captures undefined.
Use MessageSent.
The same emitter under the old binding name, so a template still binding (messageSent) keeps working. Must stay AFTER MessageSent: class fields initialise in order, and the other way round this captures undefined.
A streamed final-response delta was applied to an in-progress message: Message holds the
full reply so far. Informational, so no Before/After pair; coalesced to at most one emission
per animation frame; silent once the message has settled, because the completion path owns
the final render. Hosts refresh the bubble in place on this, while MessageSent keeps
announcing new and status-changed messages.
OptionalParentReadonlyPickerCDK connected-overlay positions for the voice agent picker. Preferred: open UPWARD,
right edge aligned to the composer's right edge (matching the old absolute placement).
Fallback: open downward when there isn't room above. Because the popover renders in the
body-level CDK overlay container (with cdkConnectedOverlayPush), it escapes the chat
overlay's overflow: hidden border and can never clip at the top of a narrow overlay.
If specified, this provider will be used for communication and for all metadata purposes. By default, if not provided, the Metadata and RunView classes are used for this and the default GraphQLDataProvider is used which is connected to the same back-end MJAPI instance as the Metadata and RunView classes. If you want to have this component connect to a different MJAPI back-end, create an instance of a ProviderBase sub-class like GraphQLDataProvider/etc, and configure it as appropriate to connect to the MJAPI back-end you want to use, and then pass it in here.
Blocks sending. Distinct from Disabled, which means the composer is busy.
When set, called once at the start of each send to get the branch of the new user row; undefined stops the send and nothing is written. A host uses it to create a draft fork on its first send.
What the send slot is doing; see SendSlotMode in @memberjunction/ng-composer.
True while the "Start a voice call with…" agent picker popover is open.
Elapsed time after the status text, kept out of the live region and dropped on narrow screens.
Status line shown bottom-left inside the composer while non-null.
The send slot was clicked in stop mode; the chat area stops the run(s).
How many things a stop would stop; above 1 the slot reads "Stop all".
Tooltip and accessible name of the slot in stop mode.
OptionalSystemThe fork new messages from this composer go to; null (the default) is Main. The agent turn of a message, and the agent-history reads it makes, use the message's branch.
Use UploadStateChanged.
The same emitter under the old binding name, so a template still binding (uploadStateChanged) keeps working. Must stay AFTER UploadStateChanged: class fields initialise in order, and the other way round this captures undefined.
True while a live voice session is active — drives the overlay + mic state.
The persisted co-agent preference, loaded just before the picker opens (and read by
the instant-start path). null = no preference / explicit "Auto".
StaticɵdirStaticɵfacUse AcceptedFileTypes.
Use AgentRunsByDetailId.
Use AgentRunsByDetailId.
Use AppContext.
Use ApplicationId.
Use ArtifactsByDetailId.
Use ArtifactsByDetailId.
Use CanSend.
Use CanStartRealtime.
True when the mic button should be enabled (have an agent + not disabled).
Use ConversationHistory.
Use ConversationId.
Use ConversationName.
Use CurrentUser.
Use DefaultAgentId.
Use Disabled.
Use EmptyStateMode.
Use EnableAgentMentions.
Use EnableAttachments.
Use EnableEntityMentions.
Use EnableMentions.
Use EnablePlanMode.
Use EnableRealtime.
Use EnableSkillCommands.
Use InitialAttachments.
Use InitialDraft.
Draft text to stage in the composer when this input mounts (NOT sent — unlike pendingMessage). Applied once per distinct value, view-readiness-proof: if the view isn't up yet, ngAfterViewInit applies it. Emits initialDraftApplied so the host can clear its pending state.
Use InitialMessage.
Use InProgressMessageIds.
Use InputBox.
Use IsProcessing.
Use IsSending.
Use MaxAttachments.
Use MessageText.
The composer's text. An accessor pair rather than a plain field because every write reaches the
editor through [value] -> ngModel.writeValue, which rebuilds or empties the chip DOM WITHOUT
emitting valueChange — so a write is exactly the event mentionedAgentId has to hear
about, and the setter is the one place that cannot be bypassed.
Bypassing it is not hypothetical: handleSuccessfulSend and the empty-state submit clear the
text without touching the editor, and conversation-chat-area assigns messageText on this
component from the outside (three call sites). Invalidating at the individual call sites instead
would leave every future one to remember.
Read is a plain field read; there is no two-way ngModel on this property (the template binds
[value]="messageText" one-way), so the pair is transparent to callers.
Use ParentMessageId.
Use PickerTargetAgentId.
The agent the '/' skill picker should narrow to. Mirrors routing's priority: an explicit
@agent chip already in the draft wins (routeMessage's Priority 1), else the agent the message
would otherwise go to (resolveCurrentAgentId). Bound to mj-ai-composer's
TargetAgentId; null = unknown, no narrowing.
Use Placeholder.
Plan Mode toggle state — sticky PER CONVERSATION, OFF by default (no behavior change unless
the user turns it on). When on, the user's next message(s) in THIS conversation request Plan
Mode: the routed root agent must present a plan for approval before executing Actions/
Sub-Agents. The toggle is always shown and the server enforces the AIAgent.SupportsPlanMode
capability — a plan-mode request to an agent that doesn't support it simply no-ops the gate
(see resolvePlanModeGate), so we don't need to resolve "the current agent" client-side.
IMPORTANT: this is a GETTER over PlanModePreference (UserInfoEngine-backed), NOT a local field. The composer is mounted in multiple places at once (empty-state, chat-area, thread panel) — a local boolean per instance goes stale the moment another instance toggles. On the new-conversation composer (no conversationId yet) the value lives in a pending bucket that transfers to the real conversation on its first message. Approving a plan turns the conversation's flag OFF automatically (see message-item's plan-decision handling).
Use ProcessingMessage.
Returns either the default Metadata provider or the one specified in the Provider property, if it was specified
Returns either the default RunQuery provider or the one specified in the Provider property, if it was specified
Returns either the default RunView provider or the one specified in the Provider property, if it was specified
Use UploadingMessage.
Use VoiceActive.
Use VoicePickerAgents.
Agents the voice picker offers — the same cached set the
autocomplete and resolveRealtimeAgentName use, narrowed to AllowedAgentIDs, so the picker can never offer an agent the conversation couldn't otherwise route to.
Use VoicePickerCoAgents.
The ACTIVE Realtime-type co-agent candidates — the same run-permission-filtered cached set as voicePickerAgents, narrowed to the Realtime agent type. The picker shows its co-agent selector only when more than one exists.
The agent the default resolution would call — preselected in the picker.
Current composer content in the lossless serialized form ('' when empty).
Pre-addresses the composer to an agent as a RESOLVED mention pill (+ trailing space, caret after, focused) — identical to the user typing '@agent' and picking it from the dropdown. Resolves the agent through MentionAutocompleteService so the chip carries the agent's real id/icon/presets; falls back to a plain-text '@Name ' draft when the agent can't be resolved (e.g. name mismatch).
false while the composer view isn't mounted yet — callers may retry.
A callback method that is invoked immediately after Angular has completed initialization of a component's view. It is invoked only once when the view is instantiated.
A callback method that is invoked immediately after the default change detector has checked data-bound properties if at least one has changed, and before the view and content children are checked.
The changed properties.
A callback method that performs custom clean-up, invoked immediately before a directive, pipe, or service instance is destroyed.
A callback method that is invoked immediately after the default change detector has checked the directive's data-bound properties for the first time, and before any of the view or content children have been checked. It is invoked only once when the directive is instantiated.
Handle attachment errors from the input box
Handle attachments changed from the input box
Handles the composer's value stream: keeps messageText in sync + emits draft state.
User confirmed an agent (+ optional co-agent / voice model / voice and its avatar) in the voice picker — start the call.
User dismissed the voice picker without starting a call.
Use OnRealtimeOptions.
Caret-next-to-the-phone click: open the agent/co-agent/model picker ON DEMAND, even when the conversation already has agent history (where the plain phone click instant-starts). The resolved agent is preselected, so "open → Start" matches the instant path while keeping the co-agent (and, for authorized users, voice-model) choice one click away. Falls through to the instant path when there is nothing to pick from.
Use OnSend.
Use OnStartRealtime.
Start a real-time voice session fronting the conversation's current agent. Client-direct: the RealtimeSessionService mints an ephemeral token and connects the browser straight to the realtime provider over WebRTC. The "call mode" overlay itself is hosted by the conversation chat area (driven by Active$).
NEW vs EXISTING conversation:
Handle text submitted from the input box
Reconnect to in-progress messages for streaming updates via global streaming service. This is called when:
Routes an existing user message through the agent path again, so the agent writes a new reply
on targetBranchId (default: the message's own branch). No message is saved, and the
composer's draft and pending attachments are left alone. The rerun never counts as the
conversation's first message. IsSending stays true until the agent turn ends, so no other
send starts meanwhile.
OptionaltargetBranchId: string | nullfalse, with no agent turn, when the composer is read-only or already sending.
Resolve the agent the voice session should front for THIS conversation. Mirrors the routing precedence used for text turns (routeMessage):
OptionalextraAttachments: PendingAttachment[]Use SendMessageWithText.
Send a message with custom text WITHOUT modifying the visible messageText input Used for suggested responses and initial messages from empty state. Also saves any pending attachments.
extraAttachments is an escape hatch for callers that programmatically
attached something via AddArtifactAttachment and want to send in the same
tick — the attachmentsChanged event chain hasn't propagated yet, so
this.pendingAttachments may not contain the attachment. Pass it in
explicitly and we merge + dedupe (by id) before saving.
options.IsResend sends an edited copy of an earlier message. The composer's draft is left
alone: only extraAttachments are saved with the message, and the pending attachments and
editor text are not cleared. The send never counts as the conversation's first message, so
it does not name the conversation or claim a pending Plan Mode choice.
options.TargetBranchID writes the message to that fork (null is Main) instead of the
composer's own target.
OptionalextraAttachments: PendingAttachment[]Optionaloptions: { IsResend?: boolean; TargetBranchID?: string | null }Toggle sticky Plan Mode for THIS conversation (or the pending-new bucket on the new-conversation composer). Writes through PlanModePreference — the PlanModeEnabled getter reads the same cached setting, so ALL live composer instances flip together, and the value survives component recreation and sessions until the user turns it off or approves a plan.
ProtectedupdateOptionalresult: ExecuteAgentResult
Base class for all Angular components in the MemberJunction system.