Skip to content

chore(examples): move the Expo agent examples to @stream-io/stream-agents 0.4.2 - #3978

Merged
isekovanic merged 3 commits into
v9-releasefrom
chore/rn-examples-stream-agents-0.4.1
Nov 12, 2026
Merged

isekovanic merged 3 commits into
v9-releasefrom
chore/rn-examples-stream-agents-0.4.1

Conversation

@oliverlaz

Copy link
Copy Markdown
Member

Ticket: https://linear.app/stream/issue/RN-524

What

  • @stream-io/calypso ^0.3.0 β†’ @stream-io/stream-agents ^0.4.1 in ExpoChatGPTSample and ExpoCrewAssistant (the same JS SDK, renamed). Imports move to @stream-io/stream-agents and /chat. stream-chat stays on 9.55; /chat supports 9 and 10. .yarnrc.yml swaps calypso for stream-agents on the age-gate allowlist, since 0.4.1 is newer than three days.
  • Each example's agent/agentChat.ts and agent/agentTransport.ts are deleted. contexts/AppContext.tsx builds the controller from new AgentChat({ sessionId, open }) and agentChatTransport(chat, { adapt, images, reasoningEffort }), with actions: { edit: false, regenerate: false }. The transport sends the controller's messageId as requestId and a generated-UI action from custom.uiAction; a failed reply shows the kit's translated error.
  • agent/conversation.ts (new, per app): the Chat/ChatState types over LocalMessage, chatStore(chat) for useStateStore (typed for stream-chat's StateStore; the SDK's store has the same shape), a React key per chat, and whenUsed, which refreshes the drawer each time a new conversation's session is used (a first question that never reached the router has its session deleted, and the retry creates another).
  • Tools.register's run is (input, call) in 0.4 and the SDK stops waiting on a cancelled call itself, so deviceTools.ts drops the abort signal.

ExpoCrewAssistant keeps in the app what the SDK doesn't do:

  • DISPLAY_TITLES for the backend's tool steps, by wrapping adapt.
  • "Crew is getting things ready" while the agent opens a conversation about an event (awaitingAgent, now on the context, derived from whether a reply has shown).
  • lastRequest for "Try again" (questions, events and voice memos). A composer retry doesn't overwrite it, so a generated-UI action keeps its uiAction.
  • Voice memos and event-opened conversations call chat.use() once the router or backend has the request, so they're kept and listed, and a failed one isn't left behind.
  • On returning to the foreground, chat.prepare() when the session's socket is no longer live.

Checks

  • yarn lint
  • yarn workspace expochatgptsample typecheck / yarn workspace expocrewassistant typecheck
  • Run on a simulator against the local router (not done: no dev client build and no Stream API key in this checkout)

…ents 0.4.1

Replace @stream-io/calypso 0.3 with @stream-io/stream-agents 0.4.1 in
ExpoChatGPTSample and ExpoCrewAssistant, and build each conversation's
AIConversationController from the SDK's AgentChat and agentChatTransport
instead of the examples' own agentChat.ts and agentTransport.ts.

What the SDK doesn't hold stays in the apps: listing a new conversation
once it is used, and in ExpoCrewAssistant the step titles, the "getting
things ready" state, retrying the last request, voice memos and reopening
a dropped session when the app comes back to the foreground.
@oliverlaz
oliverlaz requested a review from isekovanic November 11, 2026 21:51
@isekovanic
isekovanic merged commit de53971 into v9-release Nov 12, 2026
5 of 7 checks passed
@isekovanic
isekovanic deleted the chore/rn-examples-stream-agents-0.4.1 branch November 12, 2026 14:55
@isekovanic isekovanic changed the title chore(examples): move the Expo agent examples to @stream-io/stream-agents 0.4.1 chore(examples): move the Expo agent examples to @stream-io/stream-agents 0.4.2 Nov 12, 2026
isekovanic added a commit that referenced this pull request Nov 12, 2026
Port of #3978 to V10: both samples use the SDK's AgentChat and
agentChatTransport in place of calypso and their own chat layer, with
the stream-chat 10 fields read from custom. The AI_AGENT_ERROR_MESSAGE
docs no longer say to translate it.
isekovanic added a commit that referenced this pull request Nov 12, 2026
Ticket: https://linear.app/stream/issue/RN-485

## 🎯 Goal

Bring the AI agent work we shipped on `v9-release` to V10: the same
components, APIs and sample apps, adapted to stream-chat 10 and the V10
i18n.

The long-press Copy/Edit menu on the person's own messages isn't here.
It isn't on v9 either, and it comes later as a V10 feature.

## πŸ›  Implementation details

The branch is one commit per v9 PR, in merge order, then the V10-only
changes, so it can be reviewed commit by commit.

**Ported from v9**
- #3920 parse agent reply steps from message attachments
- #3921 AI translations through the chat SDK, sample on the agents
router
- #3924 agent reply steps: reasoning, tool calls, approvals
- #3926 native `AIAgent` module for the install id and tool-call sign-in
- #3928 message views, reply actions and icon overrides
- #3929 `AIConversation` on LegendList
- #3931 chat options, suggestions and attachment preview fixes
- #3933 client tool runner
- #3934 polish of agent conversations
- #3936 generated UI with an A2UI renderer
- #3944 follow-up polish of agent conversations
- #3958 A2UI list-row secrets and malformed messages
- #3957 conversation state with `AIConversationController`
- #3960 `AIConversation` in its own entry point
- #3963 the crew assistant demo app
- #3974 alignment with the other SDKs
- #3975 StrictMode-safe controller lifecycle and `custom.uiAction` docs
- #3976 crew drawer layout
- #3978 the samples on `@stream-io/stream-agents` 0.4.2, in place of
calypso and their own chat layer

Where `develop` had already changed the same lines (comment cleanups,
the i18n move, a11y docs), `develop`'s version wins.

**What's different on V10**
- **Fields under `custom`.** stream-chat 10 keeps `mime_type`,
`file_size`, `ai_generated`, `generating`, `ai_ui` and the step fields
under `custom`. `parseMessageParts` and `fromStreamMessage` lift them
with a small `withCustomFields` helper, as the React SDK does.
- **Translation keys.** The 55 AI and A2UI strings use catalog keys with
their English inline, named after React's
(`aiComponents.replyActions.copy.accessibilityLabel`,
`a2ui.modal.close.label`, …), and `keys.ts` is regenerated.
`useAITranslation` returns core's typed `t`.
- **Entry isolation.** The AI entry points may reach V10's translation
context. `@legendapp/list` and `react-native-keyboard-controller` are
AI-only packages.
- **LegendList stays at 3.7.1**, the version v9 resolves. 3.7.2 keeps
fewer rows mounted after a jump, so the reused-rows test now only
compares rows that stay mounted. It passes on both versions.
- **Sample data layer.** Both samples use stream-agents' `AgentChat`,
whose stream-chat 10 reader reads `channel.messagePaginator`, activates
the channel so the client reloads it after a reconnect, and loads older
pages with `toTail()`. The samples read the reply fields from `custom`,
and the crew sample uploads voice memos with `uploadChannelFile`.
- **Sample dependencies.** Both samples depend on
`@stream-io/state-store` and `use-sync-external-store`, and pin
`@stream-io/state-store` to one copy in `tsconfig` paths. They stay on
stream-chat `^10.0.1`: stream-agents asks for `^10.0.2`, but only when
it builds its own client, and the samples hand it theirs.

## 🎨 UI Changes

None compared with v9. The screenshots are in the v9 PRs above.

## πŸ§ͺ Testing

`yarn lint`, `yarn typecheck`, `test:typecheck`, the unit tests and
`yarn build` pass, and both samples typecheck.

On an Android emulator and an iOS simulator:
- **ChatGPT sample:** reasoning, the device time tool, the generated
Lisbon plan, the drawer, reopening a conversation from history, and
starters on a new one.
- **Crew sample:**
- all eight flows, including the approval cards, the checklist and form
actions, and the agent-first ones;
- the equipment deep link, photo troubleshooting and the team lead view;
  - voice memos, recorded on the simulator with `say` and answered;
  - the clock-out form on iOS.
- **Reconnect:** the network was dropped mid-reply on both samples. The
client recovered the active channel, and the full reply appeared.
- **Older messages:** with the page size briefly set to 3, older pages
loaded until there were none left.

After the move to stream-agents, both samples were checked again on both
platforms: replies, the device time tool, the agent-first Clock in flow,
the drawer, reopening from history, handbook sources, and an approval
card into A2UI. Reconnect, older pages and voice memos were tested on
the samples' previous chat layer, not again since.

Not tested here: voice mode (the simulator's speech recognition doesn't
hear `say`), dictation, Cal.com sign-in, and charts or photos in the
ChatGPT sample.

## β˜‘οΈ Checklist

- [x] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [x] PR targets the `develop` branch
- [x] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
  - [ ] SampleApp iOS and Android
  - [x] Expo iOS and Android
@github-actions github-actions Bot mentioned this pull request Nov 12, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants