mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-04 01:48:59 +00:00
* Require agents plugin 2.x, consolidate agent list on /ai_bots, add is_default and turn_count columns
Raises the plugin version floor to 2.0.0, drops the bridge /api/v4/agents
usage (keeping /api/v4/agents/status), renames the two observeIsAgentsEnabled
gates to observeIsAgentsVersionSupported / observeHasAvailableAgents, keys
default-agent resolution on the camelCase isDefault wire field, sorts cached
bots default-first, and adds the single schema migration (v21) for is_default
on ai_bot and turn_count on ai_thread. Adds a shared resolveAgentSelection
helper so entry points only show an agent picker when more than one agent is
available.
Unit tests, tsc and lint pass; device verification deferred to the end-of-run
test campaign.
* Plumb tool-call metadata (would_auto_execute, decided_at, mcp_bare_name) and persist web-search citations
Maps the 2.x tool-call fields the server already sends: auto-approved tools
no longer show Accept/Reject controls (an interrupted all-auto round gets a
single Run tools action, matching the webapp), already-decided results are
excluded from the share/keep-private prompt and count, MCP tools display
their server-provided bare name, empty arguments render 'No parameters
required' instead of a {} code block, and decided cards keep an
Accepted/Rejected status line.
Persisted web-search citations: extractAnnotationsFromTurn now reads the
live Annotations blocks (web_search_context.results url_citation entries),
so sources survive the stream-end refetch and thread reopen instead of
vanishing. Also ports the webapp's OpenAI inline '(source: URL)' strip.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Add AskUserQuestion interactive card and tool_answers wire
An agent question previously dead-ended on mobile: the generic tool card
sent only accepted_tool_ids, the server rejected the approval with 400
ErrInvalidToolAnswer, and the question stayed pending forever. This adds
the tool_answers map to submitToolApproval and an inline QuestionCard
(routed before the generic ToolCard for user_interaction=select calls)
with single-select immediate submit, multi-select and free-form answers
behind an explicit Submit, allow_free_form:false support, Skip, and
Answered/Skipped/Waiting status lines. Questions are excluded from batch
Accept/Reject-all, matching the webapp.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Render agent posts inside the shared post Body
Nests AgentPost as the message slot inside Body instead of substituting
the whole Body, restoring files (a files-only CreateFile reply previously
rendered empty), reactions and priority acknowledgements, and permalink
preview embeds on agent posts. Permalink detection now scans all embeds
instead of only embeds[0], matching the webapp. Post passes only two new
primitive props (isAgentPost, currentUserId); memo boundaries are
untouched and streaming state stays subscribed inside the AgentPost
subtree, so ordinary posts get zero added prop churn and streaming
re-renders stay confined to the agent subtree.
Unit tests, tsc and lint pass; device verification and the channel-view
perf sanity check deferred to the end-of-run test campaign.
* Honor unsafe_links on agent-authored markdown
The plugin tags every bot post unsafe_links=true because agent content may
be prompt-injected, and mobile's Markdown already gates links, channel
links, hashtags and LaTeX behind isUnsafeLinksPost — but the agent
renderers never passed it. Persists the global allowUnsafeLinks server
config from /ai_bots into the agents config store and passes the computed
flag into the agent post renderers and both tool-card markdown sites,
matching the webapp.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Fix agent post render gaps: stale rounds during regenerate, clipped reasoning, blank cold open
Regenerating now suppresses the cached persisted rounds (the server has
already deleted those turns) until the refetched conversation lands, so
the old answer no longer stacks above the new stream; the flag clears on
refetch, request failure, or refetch error. Long reasoning content scrolls
inside its 600dp cap via a nestedScrollEnabled region instead of being
clipped. A cold-opened agent post shows the generating placeholder while
the conversation fetch is in flight instead of rendering nothing.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Fix agent chat new-chat reset, thread message counts, and stale agent list
The + button in the agent threads list now resets the chat to a new empty
conversation (keeping the selected agent) instead of popping back into the
existing thread. History rows show the 2.x turn_count as 'N messages'
instead of always '0 replies'; the dead message preview and reply_count
plumbing are removed (schema columns dropped without a migration — orphaned
sqlite columns are ignored). The custom_mattermost-ai_bots_invalidate
websocket event now refreshes the DB-backed agent list, so agents
added/removed mid-session propagate without an app restart.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Fix channel analysis: bound unreads by since, add team_id, filter agents by channel scope, gate on license
'Summarize unreads' now sends since=lastViewedAt as ISO 8601 and drops the
nonexistent unreads_only option, which the plugin ignored — the summary was
silently unbounded. Requests carry team_id (used server-side for DM/GM
context). The agent picker filters out agents the server would 403 for the
channel (access-level predicate ported from the webapp), a zero-agent
empty state replaces the dead option list, and entry points hide when the
server lacks an enterprise-tier license (SKU entry/enterprise/advanced,
unknown-SKU MessageExport fallback, or EnableDeveloper+EnableTesting),
mirroring the plugin webapp. Adds the responses-are-private disclosure to
the summary sheet.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Add thread analysis to the post long-press menu
Adds an Ask Agents row to the post options sheet (gated on agents present
and the enterprise-tier license the plugin requires), opening a sheet with
the three analysis types: summarize thread, find action items, and find
open questions. Requests go to POST /post/{id}/analyze and the app
switches into the bot DM where the result streams, fetching the DM
membership first when the server just created it. Agent choice follows
the shared rules: channel-scope filtered, picker only when more than one
usable agent, persisted via the agents preference.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Add custom prompts consumption: new-chat pills and composer sheet entry
Prompts authored on the webapp are now usable from mobile. The agent
new-chat screen shows the user's pinned prompts as pills that server-render
the template and post into the agent DM, and the composer AI-actions sheet
gains a Custom prompts entry that renders the selected prompt into the
draft for review, prepending @agent outside bot DMs so the message actually
reaches an agent. Prompt and pin state live in an ephemeral per-server
store (no schema changes); rendering is entirely server-side.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Add unreads summarization from the New Messages separator
Adds a compact Ask AI pill on the channel view's New Messages separator
(licensed servers with at least one usable agent only; never in threads),
opening a sheet with summarize new messages, find action items, and find
open questions. Requests hit POST /channel/{id}/interval with start_time =
the separator's lastViewedAt and end_time always 0 — the server's 14-day
cap validation compares milliseconds against a seconds constant, so any
nonzero end_time fails; the webapp also always sends 0. The response
streams into the bot DM, which the app switches into.
Unit tests, tsc and lint pass; device verification deferred to the
end-of-run test campaign.
* Fix device-test findings: MCP name fallback, stale conversation after regen pause, reasoning scroll
Tool cards now strip the MCP namespace prefix when the server omits
mcp_bare_name (embedded-server tools in persisted conversations), matching
the webapp's fallback. The cached conversation refetches on stream
end/cancel from the websocket handler, so a regeneration that pauses
immediately for tool approval renders its approval card in-session and
re-entry no longer shows stale pre-regen content. The reasoning scroll
region uses the gesture-handler ScrollView so it actually scrolls inside
the inverted post list on Android.
All three verified on device; unit tests, tsc and lint pass.
* Collect only the newest generation's turns for an agent post
The backward walk in collectResponseTurns stopped only at turns anchored
to a different post, so when the server retains superseded same-post
anchor turns (the thread-analysis regenerate path does not scrub them),
every prior generation rendered stacked above the latest. Stop at any
post-anchored turn instead — mid-response turns never carry a post_id —
matching the webapp's first-anchor collection.
Verified on device against real multi-generation server data; unit tests,
tsc and lint pass.
* Address review feedback: unreads bound, refetch race, selection reconciliation, logout cleanup
The channel-summary unreads bound now uses the channel member's pre-entry
viewedAt (entering the channel advances lastViewedAt to now, emptying the
window), errors out instead of falling back to the Unix epoch, and the
interval client hard-codes end_time: 0. Conversation refetches are guarded
by an inflight-promise identity check so a superseded fetch cannot
overwrite a newer result, and the websocket-side refetch awaits inside its
try block. Agent selection in the summary, thread-analysis, unreads and
rewrite sheets follows the auto-resolved agent until the user explicitly
picks one, and resets when the pick leaves the eligible list. Bot-DM
detection for custom prompts matches only the selected agent's DM. The
custom prompts store seeds hook state from the current subject value and
is cleared on logout. Custom prompt sheet snap points stay ascending.
Also wraps a raw error log, fixes a vacuous post_options test by seeding
licence and bot state, and renames tests to the should... convention.
Unit tests and lint pass; tsc shows only the pre-existing baseline
(verified identical with changes stashed). Device environment was recycled
between rounds, so this round is unit-test verified only.
* Consolidate agent analysis sheets around a shared selection hook and sheet
Thread analysis and unreads summarization shared ~250 lines of identical
agent filtering, selection, persistence and chrome. Both now render a
generic AgentAnalysisSheet, and the channel summary sheet reuses the same
useChannelAgentSelection hook and presentational parts.
* Share the bot-DM switch across agent analysis actions
Channel summary, channel interval and thread analysis each switched into
the response DM with their own copy of the validate/fetch/switch logic;
channel summary also skipped fetching a freshly created DM. Route all three
through switchToAgentResponseChannel and stop logging raw error objects.
* Let the websocket handler own the stream-end conversation refetch
AgentPostNew refetched on every generating->false transition while
handleAgentPostUpdate already refetched on end/cancel, issuing two GETs per
settled stream. Keep the websocket handler as the single owner; it also
covers unmounted posts and coalesced start/end renders.
* Fix saveSelectedAgent mock typing in useChannelAgentSelection test
* Gate agent analysis on the plugin's Professional license tier
Agents plugin #1037 replaced the enterprise-only analysis check with a
four-level tier chart: channel and thread summarization are available from
Professional (including legacy E10/E20), with an LDAP feature fallback for
unrecognised SKUs. Professional servers previously had the summarize,
thread analysis and Ask AI entry points hidden.
* Show agent setup progress on empty response placeholders
Agents plugin #986 creates the response post empty (before a
conversation_id is attached) ahead of MCP and provider setup, and #991
reports ordered setup phases over the postupdate websocket event. Both
renderers now treat an empty agent post as working instead of drawing an
empty bubble, and show the latest phase via a shared WorkingIndicator.
* Render provider-executed server tool activity on agent posts
Agents plugin #946 streams provider-native tool activity (web search,
web fetch, sandbox code runs) as a server_tool control on postupdate and
persists it as server_tool_use content blocks. Mobile dropped both, so
responses that searched or ran code showed no activity. Track the
cumulative per-round snapshot while streaming, split persisted turns so
activity renders between the text around it, and show informational
ServerToolSet cards.
* Prefer the MCP-declared tool title on tool cards
Agents plugin #881 sends an MCP tool's resolved title (and description)
on live tool calls and persisted tool_use blocks, and the webapp displays
it instead of the prettified tool name. Map both fields from the
conversation and use the title when present.
* Drop agent exports with no callers
resetCustomPromptsState, observeCustomPromptsState and the analysis
preset/type aliases were only referenced by their own tests.
* Fall back to the post message when an agent post's conversation is stale
The conversation is cached on mount, before the response turns exist, and
only refreshed by the stream-end websocket event. If that event is missed
(socket down, app backgrounded) the finished post rendered nothing, even
on re-entry. Render post.message when no rounds are available (webapp
currentRound parity) and refetch once per post revision when a finished
post has text but no turns.
* Track tool decisions in a ref so back-to-back taps still submit
handleToolDecision and handleBatchDecision read the next decisions from a
variable assigned inside a setState updater. React only runs that updater
eagerly when no other update is pending, so a decision made before the
previous one re-rendered saw no decisions and never submitted the batch.
* Derive the selected agent instead of mutating a ref inside a state updater
useAgentSelection cleared its user-selection ref inside the setSelectedAgent
updater, which React may replay or discard. Keep the explicit pick in state
and derive the selection from it and the auto-resolved agent.
* Ignore a custom prompt render that finishes after its sheet closed
Closing the prompt list while a render was in flight still wrote the result
into the composer draft and dismissed whatever sheet was open. Also type
channelId as optional, which the composer entry point can omit.
* Report a failed switch to the agent response DM
switchToAgentResponseChannel ignored switchToChannelById's result, so the
analysis actions reported success when the switch failed.
* Render URL-less citations as plain rows
Persisted web-search annotations may omit url; those rows still looked
like links (domain line and open-in-new icon) but did nothing on tap.
* Tidy agent review nits: reuse the defined message, drop a non-null assertion, should-names
* Hide agent entry points when the plugin is disabled or no agent is usable
Gate the composer rewrite, Ask agents post option and Ask AI pill on a
supported plugin version plus a usable agent (scoped to the channel for the
post option and pill); rewrite also needs the core AI bridge. Clear stored
bots when the plugin is disabled, purge stale rows when the server returns an
empty list, and let the New Messages line observe viewedAt itself.
* Share one AI bot sync per server and skip it without a supported plugin
* Gate agent analysis on Enterprise for plugins older than 2.8
* Refetch the conversation after a tool decision and allow retrying a failed one
A channel accept returns without streaming or any event, so the share step
never appeared; a failed submit left cards without buttons and questions on
Submitting.
* Post custom prompt pills as the current user and drop results after an agent switch
* Keep streamed agent content until the post-stream refetch lands
The plugin edits the post before sending end, so POST_EDITED dropped the
streaming state before the refreshed conversation arrived and reasoning,
tool cards and resumed answers blinked out. The end handler now drops it in
the same update that delivers the refetch, and reconnect settles streams
whose end was missed.
Also keep generating true through reasoning, tool and annotation events,
discard an in-flight fetch when regenerating so it cannot resurface the old
answer, let the requester act on a live pending tool call, and memoize
RoundView.
* Drop calls to the private tool-data routes removed in plugin 2.0
With the 2.0 floor every supported server answers them with 404, so the
legacy renderer showed an error snackbar on redacted posts. Also drop the
unreachable pre-2.0 thread normalisation.
* Seed useAgentsConfig from the current value and reset it on logout
* Log agent request errors as messages instead of raw error objects
* Build the channel summary sheet on the shared analysis sheet frame
Both sheets now share the picker, empty state, privacy footer and overlay,
and submit through one hook whose synchronous guard stops a double tap from
sending two requests. The sheet computes the unreads bound from viewedAt and
hides that option when there is no previous visit, so requestChannelSummary
no longer fetches the source channel. Channel analyses send the webapp's
per-option analysis_type labels.
* Share agent pick-and-save across the analysis sheets, rewrite and agent chat
useSavedAgentSelection replaces the channel-only hook and the hand-rolled
copies in the rewrite sheet and agent chat; agent chat now also re-resolves
when its selected agent disappears, and re-picking the current agent no
longer clears its DM channel.
* Drop unused agent queries and type the bot list fields as the wire sends them
* Tidy agent UI nits: cap server tool output, unique citation keys, a11y roles
Also align the question Submitting string with the tool cards, give the
thread analysis sheet its own testID, and fix the channel interval doc.
* Keep code intact when stripping inline agent citations
* Re-emit the agent list when bot fields change
* Harden the post-stream hand-off to the refetched conversation
* Share agent post stop/regenerate controls so legacy posts honor Stop
* Reset the agent chat conversation whenever the selected agent changes
* Gate the channel Ask Agents action on usable agents and license
* Pass lastViewedAt to the New Messages line instead of re-observing it
* Show only permalink previews under agent posts
* Fix test typings for the Ask Agents prop and opengraph embed
* Tidy tool approvals: decision-gated warning, resumed-round state, answered questions
* Show loading and error states for custom prompts; keep prompts when pins fail
* Check the plugin version before syncing bots on plugin enable
* Treat the first bot as default for plugins that omit isDefault
* Give the thread Ask Agents option its own translation id
* Share one request helper across the agent analysis actions
* Share the agent picker observables across sheets and screens
* Remove dead agent code: pre-2.0 team_ids, unused invalidate/evict, selection wrapper
* Agent UI nits: JSON payload guards, a11y roles, unique citation testIDs
* Agents: serialize bot sync per server so refreshes and clears are never lost
A fetch requested while another is running is queued (coalesced) instead of joining a request that may predate the change, and clearAIBots goes through the same queue so an in-flight fetch can't restore cleared bots.
* Agents: keep a still-running stream's state across a reconnect
After a reconnect the streaming state is only dropped once the refetched conversation holds a newer response anchor for the post; otherwise a live stream kept losing its rounds, tool calls and citations when the refetch landed before its next event.
* Agents: keep settle callbacks queued when a conversation fetch is cancelled
Cancelling (e.g. on regenerate) wrote nothing to the cache, so draining the callbacks dropped streamed content while the cache still held the old conversation.
* Agents: don't let a stale conversation error end regenerate early
An error cached before the regenerate tap lifted the suppression before the new stream started, stacking the old answer above it. Only an error from a fetch since the tap counts now.
* Agents: keep tool decisions when the live round becomes the persisted round
The anchor round keeps a stable key, so partial batch decisions, typed answers and an in-flight submit survive the stream-end refetch instead of remounting.
* Agents: harden tool approval submits
Guard submits with a ref so Accept and Reject on one card can't both submit, only submit decisions for tools that are still actionable, recover Run tools when the follow-up refetch fails, and offer only Reject for questions the app can't render (accepting them without an answer is rejected by the server).
* Agents: handle parenthesised URLs and more code forms when stripping citations
Citation URLs may contain one level of balanced parentheses, and indented code, longer fences and multi-backtick code spans are now left untouched.
* Agents: settle a finished stream when its post edit is stored after end
Websocket handlers aren't awaited, so the stream's end can be handled before POST_EDITED stores the conversation-backed post; settlement then found no conversation_id and left the streaming state behind.
* Agents: ignore a stale DM lookup after switching agents in agent chat
A late createDirectChannel result for the previously selected agent could replace the current agent's channel, so the draft posted to the wrong DM.
* Agents: don't clear another server's conversation fetches on logout
Conversation cache keys joined the server URL and id with ':', so clearing https://a.com also matched https://a.com:8065 and left that server's conversation stuck loading.
* Agents: post only one custom prompt when two pills are tapped at once
The busy guard was React state, so taps on two pills in the same frame both posted. Adds tests for the pills.
* Agents: test result sharing and question batches in tool approvals
Covers share/keep-private submission, the call-to-result stage reset, a question answered alongside other tools, Accept all skipping questions, and free-form trimming. Drops the actionable-decision filter in applyDecisions, which duplicated the pruning effect and could not be exercised.
* Agents: cover channel summary payloads, license tiers, rewrite gating and bot updates
Adds tests for the channel summary options, every licensed SKU at the plugin 2.8 boundary, the AI rewrite bridge requirement, moving the default bot and clearing access lists, the stale agent-chat DM lookup, and the new-chat reset.
* Agents: remove redundant and vacuous tests
* Agents: limit to tool approval, AskUserQuestion and stream hand-off fixes
---------
(cherry picked from commit
|
||
|---|---|---|
| .. | ||
| base | ||
| certs | ||
| fonts | ||
| sounds | ||