Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e7a265f
feat: test webview search
zhu-xiaowei Nov 7, 2025
3447e72
feat: support sitation display
zhu-xiaowei Nov 24, 2025
696e9f8
feat: speed up web search
zhu-xiaowei Nov 24, 2025
c55a3a6
feat: add search icon
zhu-xiaowei Nov 27, 2025
51f1a70
fix: remove comments
zhu-xiaowei Nov 27, 2025
d48a267
feat: add websearch for tavily and selection modal
zhu-xiaowei Dec 9, 2025
d2ecb6e
feat: support abort websearch
zhu-xiaowei Dec 9, 2025
7413d33
feat: change tavily to default provider
zhu-xiaowei Dec 9, 2025
c78f344
fix: lint and format issues
zhu-xiaowei Dec 10, 2025
0064078
fix: error log and second search
zhu-xiaowei Dec 10, 2025
ba709b5
feat: support show citation badge
zhu-xiaowei Dec 10, 2025
bfeeaa2
feat: remove logs
zhu-xiaowei Dec 10, 2025
31554a9
fix: optimize mac enter command, mermaid download, text model selection
zhu-xiaowei Dec 12, 2025
47a3816
feat: optimize code renderer
zhu-xiaowei Dec 12, 2025
46b432b
feat: add app
zhu-xiaowei Dec 12, 2025
054e314
feat: save app and support app gallery
zhu-xiaowei Dec 12, 2025
e53a30f
fix: code renderer performance
zhu-xiaowei Dec 14, 2025
fd5aa3d
feat: remove extra gestureHandler for HtmlFullScreenViewer
zhu-xiaowei Dec 14, 2025
80ab558
feat: support fullscreen switch
zhu-xiaowei Dec 14, 2025
841ec7e
feat: support Image gallery, fix lint
zhu-xiaowei Dec 14, 2025
d2508eb
feat: support create app and long click modal for app
zhu-xiaowei Dec 14, 2025
217586f
feat: remove border
zhu-xiaowei Dec 14, 2025
17cea2f
feat: update model price, remove readme
zhu-xiaowei Dec 14, 2025
8473fcd
feat: optimize code render performance, support save app to file and …
zhu-xiaowei Dec 14, 2025
a5bef6b
feat: fix lint
zhu-xiaowei Dec 14, 2025
d407303
Merge branch 'main' into web-search
zhu-xiaowei Dec 14, 2025
370fcf1
feat: support display build number, support clear all data
zhu-xiaowei Dec 15, 2025
27ad407
fix: update input bottom offset for keyboard
zhu-xiaowei Dec 15, 2025
ea7eddb
fix: add goback for create image
zhu-xiaowei Dec 15, 2025
877942c
feat: change image and app screen to drawer navigation
zhu-xiaowei Dec 15, 2025
9e463a5
feat: add app name auto fill, add retry for app screenshot
zhu-xiaowei Dec 15, 2025
2cb62fe
feat: optimize webview load animation
zhu-xiaowei Dec 15, 2025
e9558a4
feat: compat nova sonic, support localStorage
zhu-xiaowei Dec 15, 2025
1823176
feat: fix gallery display logic
zhu-xiaowei Dec 15, 2025
94f3a56
feat: support apigateway for streaming invoke up to 15 minutes
zhu-xiaowei Dec 16, 2025
ba379ca
feat: update doc, fix tempalte action add lambda InvokeFunction
zhu-xiaowei Dec 16, 2025
18201cd
feat: optimize the code renderer, add screen keep awake, change to sw…
zhu-xiaowei Dec 17, 2025
2891110
fix: code preview toggle scroll issue
zhu-xiaowei Dec 18, 2025
e399fd2
fix: save app scroll issue
zhu-xiaowei Dec 18, 2025
16dfbea
fix: android ui and websearch issue
zhu-xiaowei Dec 18, 2025
581ebc6
feat: add fullscreen for android
zhu-xiaowei Dec 18, 2025
57d502c
docs: update whats new
zhu-xiaowei Dec 18, 2025
8707487
fix: viperlight scan issues
zhu-xiaowei Dec 18, 2025
6e859ec
fix: ash and trivy scan issues
zhu-xiaowei Dec 19, 2025
d37ba13
fix: lint issue
zhu-xiaowei Dec 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 22 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,11 @@ across Android, iOS, and macOS platforms.
![](assets/promo.avif)

### What's New 🔥
- 🚀 Support Web Search for real-time information retrieval (From v2.7.0).
- 🚀 Support Create App to generate and preview mini web applications (From v2.7.0).
- 🚀 Support Image Gallery for browsing and managing generated images (From v2.7.0).
- 🚀 Support streaming rendering of Mermaid charts (From v2.6.0).
<div style="display: flex; flex-direction: 'row'; background-color: #888888;">
<img src="assets/animations/mermaid_en.avif" width=48%>
<img src="assets/animations/mermaid_save_en.avif" width=48%>
</div>
- 🚀 Support using Bedrock API Key for Amazon Bedrock models (From v2.5.0).
- 🚀 Support virtual try-on, automatically recognize clothes, pants, shoes and try them on (From v2.5.0).
- 🚀 Support shortcuts for macOS (From v2.5.0).
- Use `Shift + Enter`, `Control + Enter` or `Option + Enter` to add a line break.
- Use `⌘ + V` to add images (Screenshot), videos, or documents from your clipboard.
- Use `⌘ + N` to opening multiple Mac windows for parallel operations.

## 📱 Quick Download

Expand All @@ -36,11 +30,6 @@ across Android, iOS, and macOS platforms.

## Getting Started with Amazon Bedrock

### Prerequisites

Click [Amazon Bedrock Model access](https://console.aws.amazon.com/bedrock/home#/modelaccess) to enable your models
access.

### Configuration

You can choose one of the following two methods for configuration
Expand All @@ -64,14 +53,9 @@ You can choose one of the following two methods for configuration

### Architecture

![](/assets/architecture.avif)
![](/assets/architecture.png)

By default, we use **AWS App Runner**, which is commonly used to host Python FastAPI servers, offering high performance,
scalability and low latency.

Alternatively, we provide the option to replace App Runner with **AWS Lambda** using Function URL for a more
cost-effective
solution, as shown in
We use **API Gateway** combined with **AWS Lambda** to enable streaming responses for up to 15 minutes, as shown in
this [example](https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming).

### Step 1: Set up your API Key
Expand Down Expand Up @@ -107,34 +91,28 @@ this [example](https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examp
- ECR repository name (or use default: `swift-chat-api`)
- Image tag (please use default: `latest`)
- AWS region (the region you want to deploy, e.g.,: `us-east-1`)
- Deployment type:
- Option 1 (default): **AppRunner** - uses amd64 architecture
- Option 2: **Lambda** - uses arm64 architecture

4. The script will build and push the Docker image to your ECR repository.

5. **Important**: Copy the image URI displayed at the end of the script output. You'll need this in the next step.

### Step 3: Deploy stack and get your API URL

1. Download the CloudFormation template you want to use:
- For App Runner: [SwiftChatAppRunner.template](https://github.com/aws-samples/swift-chat/blob/main/server/template/SwiftChatAppRunner.template)
- For Lambda: [SwiftChatLambda.template](https://github.com/aws-samples/swift-chat/blob/main/server/template/SwiftChatLambda.template)
1. Download the CloudFormation template:
- Lambda: [SwiftChatLambda.template](https://github.com/aws-samples/swift-chat/blob/main/server/template/SwiftChatLambda.template)

2. Go to [CloudFormation Console](https://console.aws.amazon.com/cloudformation/home#/stacks/create/template?stackName=SwiftChatAPI) and select **Upload a template file** under **Specify template**, then upload the template file you downloaded. (Make sure you are in the same region where your API Key was created.)

3. Click **Next**, On the "Specify stack details" page, provide the following information:
- **Stack name**: Keep the default "SwiftChatAPI" or change if needed
- **ApiKeyParam**: Enter the parameter name you used for storing the API key (e.g., "SwiftChatAPIKey")
- **ContainerImageUri**: Enter the ECR image URI from Step 2 output
- For App Runner, choose an **InstanceTypeParam** based on your needs

4. Click **Next**, Keep the "Configure stack options" page as default, Read the Capabilities and Check the "I
acknowledge that AWS CloudFormation might create IAM resources" checkbox at the bottom.
5. Click **Next**, In the "Review and create" Review your configuration and click **Submit**.

Wait about 3–5 minutes for the deployment to finish, then click the CloudFormation stack and go to **Outputs** tab, you
can find the **API URL** which looks like: `https://xxx.xxx.awsapprunner.com` or `https://xxx.lambda-url.xxx.on.aws`
can find the **API URL** which looks like: `https://xxx.execute-api.us-east-1.amazonaws.com/v1`

### Step 4: Open the App and setup with API URL and API Key

Expand Down Expand Up @@ -271,10 +249,15 @@ can enable the **Use Proxy** option to forward your requests.

![](assets/animations/english_teacher.avif)

**Rich Markdown Support**: Paragraph, Code Blocks, Tables, LaTeX and More
**Rich Markdown Support**: Paragraph, Code Blocks, Tables, LaTeX, Mermaid and More

![](assets/markdown.avif)

<div style="display: flex; flex-direction: 'row'; background-color: #888888;">
<img src="assets/animations/mermaid_en.avif" width=48%>
<img src="assets/animations/mermaid_save_en.avif" width=48%>
</div>

We redesigned the UI with optimized font sizes and line spacing for a more elegant and clean presentation.
All of these features are also seamlessly displayed on Android and macOS with native UI

Expand Down Expand Up @@ -464,10 +447,14 @@ the [release notes](https://github.com/aws-samples/swift-chat/releases) to see i

### Upgrade API

- **For AppRunner**: Click and open [App Runner Services](https://console.aws.amazon.com/apprunner/home#/services) page,
find and open `swiftchat-api`, click top right **Deploy** button.
- **For Lambda**: Click and open [Lambda Services](https://console.aws.amazon.com/lambda/home#/functions), find and open
your Lambda which start with `SwiftChatLambda-xxx`, click the **Deploy new image** button and click Save.
1. First, re-run the build script to update the image:
```bash
cd server/scripts
bash ./push-to-ecr.sh
```

2. Click and open [Lambda Services](https://console.aws.amazon.com/lambda/home#/functions), find and open
your Lambda which starts with `SwiftChatAPILambda-xxx`, click the **Deploy new image** button and click Save.

## Security

Expand Down
55 changes: 22 additions & 33 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,11 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https
![](assets/promo.avif)

### 新功能 🔥

- 🚀 支持网络搜索,获取实时信息(自 v2.7.0 起)。
- 🚀 支持创建应用,生成并预览迷你 Web 应用(自 v2.7.0 起)。
- 🚀 支持图片画廊,浏览和管理生成的图片(自 v2.7.0 起)。
- 🚀 支持流式渲染 Mermaid 图表(自 v2.6.0 起)。
<div style="display: flex; flex-direction: 'row'; background-color: #888888;">
<img src="assets/animations/mermaid.avif" width=48%>
<img src="assets/animations/mermaid_save.avif" width=48%>
</div>
- 🚀 支持使用 Bedrock API Key 连接 Amazon Bedrock 模型(自 v2.5.0 起)。
- 🚀 支持虚拟试衣功能,自动识别衣服、裤子、鞋子并试穿(自 v2.5.0 起)。
- 🚀 支持 macOS 快捷键操作(自 v2.5.0 起)。
- 使用 `Shift + Enter`、`Control + Enter` 或 `Option + Enter` 添加换行。
- 使用 `⌘ + V` 从剪贴板添加图片(截图)、视频或文档。
- 使用 `⌘ + N` 打开多个 Mac 窗口进行并行操作。

## 📱 快速下载

Expand All @@ -36,10 +29,6 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https

## Amazon Bedrock 入门指南

### 前置条件

点击 [Amazon Bedrock 模型访问](https://console.aws.amazon.com/bedrock/home#/modelaccess) 启用您的模型访问权限。

### 配置

您可以选择以下两种配置方法中的一种
Expand All @@ -60,12 +49,9 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https

### 架构

![](/assets/architecture.avif)

默认情况下,我们使用 **AWS App Runner**,它通常用于托管 Python FastAPI 服务器,提供高性能、可扩展性和低延迟。
![](/assets/architecture.png)

或者,我们提供用 **AWS Lambda** 使用 Function URL 替代 App Runner
的选项,以获得更具成本效益的解决方案,如此 [示例](https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming)
我们提供用 **API Gateway** 与 **AWS Lambda** 结合的方式,实现最长15分钟的流式传输,如此 [示例](https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming)
所示。

### 步骤 1:设置您的 API 密钥
Expand Down Expand Up @@ -100,32 +86,26 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https
- ECR 仓库名称(或使用默认值:`swift-chat-api`)
- 镜像标签(请使用默认值:`latest`)
- AWS 区域(填写你希望部署的区域,例如:`us-east-1`)
- 部署类型:
- 选项 1(默认):**AppRunner** - 使用 amd64 架构
- 选项 2:**Lambda** - 使用 arm64 架构

4. 脚本将构建并推送 Docker 镜像到您的 ECR 仓库。

5. **重要**:复制脚本输出末尾显示的镜像 URI。您将在下一步中需要它。

### 步骤 3:部署堆栈并获取 API URL

1. 下载您想使用的 CloudFormation 模板:
- App Runner:[SwiftChatAppRunner.template](https://github.com/aws-samples/swift-chat/blob/main/server/template/SwiftChatAppRunner.template)
1. 下载 CloudFormation 模板:
- Lambda:[SwiftChatLambda.template](https://github.com/aws-samples/swift-chat/blob/main/server/template/SwiftChatLambda.template)

2. 前往 [CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/home#/stacks/create/template?stackName=SwiftChatAPI),在**指定模板**下选择**上传模板文件**,然后上传您下载的模板文件。(确保您所在的区域与创建 API Key 的区域相同。)

3. 点击 **下一步**,在"指定堆栈详细信息"页面,提供以下信息:
- **Stack name**:保持默认的 "SwiftChatAPI" 或根据需要更改
- **ApiKeyParam**:输入您用于存储 API 密钥的参数名称(例如 "SwiftChatAPIKey")
- **ContainerImageUri**:输入步骤 2 输出的 ECR 镜像 URI
- 对于 App Runner,根据您的需求选择 **InstanceTypeParam**

4. 点击 **下一步**,保持"配置堆栈选项"页面为默认,阅读功能并勾选底部的"我确认 AWS CloudFormation 可能会创建 IAM 资源"复选框。
5. 点击 **下一步**,在"审核并创建"中检查您的配置并点击 **提交**。

等待约 3-5 分钟完成部署,然后点击 CloudFormation 堆栈并转到 **输出** 选项卡,您可以找到 **API URL**,类似于:`https://xxx.xxx.awsapprunner.com` 或 `https://xxx.lambda-url.xxx.on.aws`
等待约 3-5 分钟完成部署,然后点击 CloudFormation 堆栈并转到 **输出** 选项卡,您可以找到 **API URL**,类似于:`https://xxx.execute-api.us-east-1.amazonaws.com/v1`

### 步骤 4:打开应用并使用 API URL 和 API Key 进行设置

Expand Down Expand Up @@ -249,7 +229,7 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https

<div style="display: flex; flex-direction: 'row'; background-color: #888888;">
<img src="assets/animations/gen_image.avif" width=24%>
<img src="assets/animations/virtual_try_on.avif" width=24%>
<img src="assets/animations/virtual_try_on_demo.avif" width=24%>
<img src="assets/animations/similar_style.avif" width=24%>
<img src="assets/animations/remove_background.avif" width=24%>
</div>
Expand All @@ -258,10 +238,15 @@ SwiftChat 是一款快速响应的 AI 聊天应用,采用 [React Native](https

![](assets/animations/english_teacher.avif)

**丰富的 Markdown 支持**:段落、代码块、表格、LaTeX 等
**丰富的 Markdown 支持**:段落、代码块、表格、LaTeX、Mermaid

![](assets/markdown.avif)

<div style="display: flex; flex-direction: 'row'; background-color: #888888;">
<img src="assets/animations/mermaid.avif" width=48%>
<img src="assets/animations/mermaid_save.avif" width=48%>
</div>

我们重新设计了 UI,优化了字体大小和行间距,提供更优雅、清洁的展示效果。
所有这些功能也在 Android 和 macOS 上以原生 UI 无缝显示

Expand Down Expand Up @@ -441,10 +426,14 @@ npm run ios

### 升级 API

- **对于 AppRunner**:点击打开 [App Runner 服务](https://console.aws.amazon.com/apprunner/home#/services) 页面,找到并打开
`swiftchat-api`,点击右上角 **部署** 按钮。
- **对于 Lambda**:点击打开 [Lambda 服务](https://console.aws.amazon.com/lambda/home#/functions) 页面,找到并打开以
`SwiftChatLambda-xxx` 开头的 Lambda,点击 **部署新镜像** 按钮并点击保存。
1. 首先重新运行构建脚本以更新镜像:
```bash
cd server/scripts
bash ./push-to-ecr.sh
```

2. 点击打开 [Lambda 服务](https://console.aws.amazon.com/lambda/home#/functions) 页面,找到并打开以
`SwiftChatAPILambda-xxx` 开头的 Lambda,点击 **部署新镜像** 按钮并点击保存。

## 安全

Expand Down
Binary file removed assets/architecture.avif
Binary file not shown.
Binary file added assets/architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class MainApplication : Application(), ReactApplication {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
add(NavigationBarPackage())
}

override fun getJSMainModuleName(): String = "index"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.aws.swiftchat

import android.graphics.Color
import android.os.Build
import android.view.View
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

class NavigationBarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

override fun getName(): String = "NavigationBarModule"

@ReactMethod
fun setImmersiveMode(enabled: Boolean) {
val activity = currentActivity ?: return

activity.runOnUiThread {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (enabled) {
// Make navigation bar transparent and content extend behind it
activity.window.setDecorFitsSystemWindows(false)
activity.window.navigationBarColor = Color.TRANSPARENT
} else {
activity.window.setDecorFitsSystemWindows(true)
}
} else {
@Suppress("DEPRECATION")
if (enabled) {
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
activity.window.navigationBarColor = Color.TRANSPARENT
} else {
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION.inv() and
View.SYSTEM_UI_FLAG_LAYOUT_STABLE.inv()
}
}
}
}

@ReactMethod
fun resetToDefault() {
val activity = currentActivity ?: return

activity.runOnUiThread {
// Trigger MainActivity's updateNavigationBarColor
if (activity is MainActivity) {
// Reset immersive mode first
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
activity.window.setDecorFitsSystemWindows(true)
} else {
@Suppress("DEPRECATION")
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION.inv() and
View.SYSTEM_UI_FLAG_LAYOUT_STABLE.inv()
}
}

// Restore default navigation bar color based on theme
val isDarkMode = activity.resources.configuration.uiMode and
android.content.res.Configuration.UI_MODE_NIGHT_MASK ==
android.content.res.Configuration.UI_MODE_NIGHT_YES

activity.window.navigationBarColor = if (isDarkMode) Color.BLACK else Color.WHITE
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.aws.swiftchat

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager

class NavigationBarPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(NavigationBarModule(reactContext))
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
Loading