Repository navigation
feat(ai-components): native AIAgent module for install id and tool-call sign-in - #3926
Open
isekovanic wants to merge 1 commit into
Open
isekovanic wants to merge 1 commit into
isekovanic wants to merge 1 commit into
Conversation
Contributor
SDK Size
|
2 of 6 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket: https://linear.app/stream/issue/RN-485
Stacked on #3924.
🎯 Goal
Let a person sign in when an agent's tool needs a connector account (Linear, GitHub, …), and give each install a stable id so the router can ask only this device. This needs a small native module,
AIAgent, which works the same way as Swift's and Android's AI SDKs.🛠 Implementation details
Native
AIAgentTurboModule (in both wrappers, sources inshared-native/)installId()is synchronous and creates an id on first use, then keeps it.ios-<UUID>inUserDefaults.android-<UUID>to a file innoBackupFilesDir, so a device restored from a backup gets its own id. The file name and format match the Android AI SDK.openAuthSession(url, callbackScheme)resolves with the redirect URL, or''when the person closes the sign-in.ASWebAuthenticationSession, ported from Swift'sAIWebAuthentication. It needs no usage description, so it's always compiled; the podspecs only addAuthenticationServices.onNewIntent. Coming back to the app without a redirect counts as closed.Auth Tab needs
androidx.browser1.9.0, and 1.9.0 needs compileSdk 36 and AGP 8.9.1. Our minimum, RN 0.76, ships with 35. The wrappers' Gradle files check both:sync-shared-native.shcopies both variants over.No new permission. The manifest adds a
<queries>entry for Custom Tabs services, which Android 11+ needs in order to find the browser.The codegen spec is copied into each wrapper, and
validate-entry-isolationkeeps the copies identical.JS (
ai-components)AIClientIdentity.installId()reads the native id. If the module isn't there, it falls back to an id kept in memory.createAuthSessionAuthorizer({ callbackScheme, decline })opens the tool's sign-in aturl#handoff_token=…and readsstatusfrom the return. "Not now" callsdecline.AIToolAuthorizationandAIToolAuthorizationCard, shown under a tool call that's waiting for a sign-in, have these states:connectedreturn until the step changes;messageParts.authorizationCardsection.arandhecould use a native speaker's look.ExpoChatGPTSample
client_id, and its sessions set areturn_urlonio.getstream.expochatgptsample://sign-in. The router only accepts https or reverse-domain schemes there.+native-intent.tsxkeeps Expo Router from opening that return URL as a screen.MessageListdoesn't re-render a row when only an attachment changes, such as a tool call starting to wait for a sign-in.connector_authorizationattachment.🎨 UI Changes
The sign-in card under a tool call: Connect / Not now, Connecting..., and its outcomes.
🧪 Testing
Unit tests cover the launch URL, reading the return, the authorizer, and the card's states.
On an Android emulator (API 36), against a local Vision-Agents router with the Linear connector:
connectedreturn shows Connecting...;The return was sent with
adb. I didn't sign into a real Linear account. I ran both Gradle variants, the Auth Tab one and a forced Custom Tab one.On an API 34 emulator (Chrome 113, no Auth Tab), the same flow works through the Custom Tab.
On the iOS simulator: the card, the
ASWebAuthenticationSessionprompt, Cancel resetting the card, and Not now.On the minimum supported setup, a bare RN 0.76.9 app (compileSdk 35, AGP 8.6) that uses the packed
stream-chat-react-nativebuilds againstandroidx.browser1.8.0. On Android 7.0 (API 24) and Android 14,installId(), an app-scheme return and closing the browser all work.The RN CLI wrapper also builds in SampleApp (compileSdk 37, so 1.9.0). I didn't run SampleApp itself.
Not tested: RTL and screen readers.
yarn lint,yarn typecheck,yarn buildandyarn test:unitpass.☑️ Checklist
developbranch (stacked on feat(ai-components): agent reply steps (reasoning, tool calls, approvals) #3924)