npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@swift-agents/react-native

v1.0.0

Published

React Native/Expo UI and typed client for the Swift Agents SDK API.

Readme

@swift-agents/react-native

React Native/Expo UI and typed client for the Swift Agents SDK API.

Configuration

The host supplies only the four values required to initialize a session:

import {
  SwiftAgents,
  SwiftAgentsProvider,
  type SwiftAgentsConfig,
} from "@swift-agents/react-native";

const config: SwiftAgentsConfig = {
  baseUrl: process.env.EXPO_PUBLIC_SWIFT_AGENTS_BASE_URL ?? "",
  companyId: process.env.EXPO_PUBLIC_SWIFT_AGENTS_COMPANY_ID ?? "",
  apiKey: process.env.EXPO_PUBLIC_SWIFT_AGENTS_API_KEY ?? "",
  userEmail: process.env.EXPO_PUBLIC_SWIFT_AGENTS_USER_EMAIL ?? "",
};

export function Support() {
  return (
    <SwiftAgentsProvider config={config}>
      <SwiftAgents onClose={() => {/* dismiss the host surface */}} />
    </SwiftAgentsProvider>
  );
}

EXPO_PUBLIC_SWIFT_AGENTS_BASE_URL is the backend origin, for example https://backend.example.com. The SDK appends /api/v1/sdk; do not add that path to the configured value.

Initialization starts when SwiftAgents opens. Missing values render an in-app configuration error and do not trigger a retry loop.

Session-token lifecycle

The SDK calls POST /api/v1/sdk/{companyId}/init with:

  • X-API-Key: apiKey
  • Content-Type: application/json
  • { "email": userEmail }

The returned session_token is held in memory by the central client. It is never rendered, logged, exposed through the UI hooks, or persisted. Every later request uses Authorization: Bearer <session_token>.

The SDK clears the token when initialization fails or the session receives a 401/403. The host can retry the visible initialization error by remounting the SDK or pressing its retry action.

Company branding and prompts

company.name and company.logo_url from /init populate the header. The home screen displays company.suggested_ai_prompts only when enable_suggested_prompts is true.

Conversations

The client calls:

  • GET /api/v1/sdk/{companyId}/conversations?limit=20
  • GET /api/v1/sdk/{companyId}/conversations?limit=20&cursor={next_cursor}
  • GET /api/v1/sdk/{companyId}/conversations/{encodeURIComponent(conversationId)}

The sliding sidebar preserves API order, supports chats and tickets, deduplicates IDs, handles loading/empty/error/retry states, and shows No recent conversations yet for an empty response. Selecting a row loads its complete messages array; it never reconstructs history from last_message.

SSE chat

Chat uses a POST fetch request because the API requires a JSON body and bearer header:

POST /api/v1/sdk/{companyId}/chat
Accept: text/event-stream
Content-Type: application/json
Authorization: Bearer <session_token>

Each new chat generates a client-side session_id before this first request. Existing chat conversation IDs are reused, and the same ID is sent for later messages in that chat.

The SDK buffers lines and frames before parsing. It supports LF/CRLF, split lines and JSON, multiple events per chunk, heartbeats, malformed individual events, unknown stages, final buffered data, cancellation, and stream cleanup. It does not use browser EventSource.

The documented stages map to the UI as follows:

  • chat_details: confirms the client-generated active session ID (or supplies a server-canonical ID) for subsequent sends.
  • subject: updates the active conversation title.
  • thinking: updates one searching indicator; it does not create bubbles.
  • stream: progressively updates one assistant bubble.
  • done: finalizes the bubble, clears streaming state, patches the active recent, and refreshes conversations.

Attachments

The SDK uses Expo DocumentPicker for multi-file selection. Local previews remain visible while sending. On send it:

  1. POSTs every local file under the repeated multipart key files.
  2. Receives remote attachment descriptors.
  3. Sends only those remote descriptors in the chat JSON body.
  4. Clears local selections only after the chat request completes successfully.

The SDK never sends a local device URI to /chat, never sets a multipart boundary manually, and prevents a text-only fallback when upload fails.

Consumers using Expo should provide expo-document-picker as a peer dependency. The example app already includes it.

Ticket reopening

Resolved ticket conversations expose the existing reopen action. It calls:

POST /api/v1/sdk/{companyId}/tickets/{encodeURIComponent(ticketId)}/reopen
Authorization: Bearer <session_token>

Any successful 2xx response is accepted, including JSON, an empty body, and 204 No Content. The ticket is marked unresolved only after success, messages remain intact, and recents refresh. Failures preserve the current resolved state and display a safe message.

Error and request states

The provider and hooks expose initialization, conversation, upload, thinking, streaming, and reopen state. Requests use abort signals, stale conversation responses are ignored, and duplicate pagination/send operations are blocked. Backend message, detail, and error shapes are normalized without exposing request headers, tokens, keys, stack traces, or internal server details.

The caret continues to call the optional host-provided onClose callback. Opening the hamburger sidebar does not cancel an active stream; closing/unmounting the SDK does.

Environment setup

Copy apps/example/.env.example to apps/example/.env and supply local values. The Postman collection does not define a backend base URL, so use the actual URL provided by your backend environment. The example configuration reads only EXPO_PUBLIC_SWIFT_AGENTS_* variables.

Expo public variables are bundled into the application. EXPO_PUBLIC_SWIFT_AGENTS_API_KEY must therefore be a restricted client/publishable SDK key, never a privileged backend secret. Keep real values in ignored local environment files and never commit them.

Public API

The package exports SwiftAgents, SwiftAgentsProvider, the existing screen/components, useSwiftAgents, useSwiftAgentsChat, useSwiftAgentsRecents, createSwiftAgentsClient, SwiftAgentsApiError, SwiftAgentsSseParser, and the typed Postman contracts.