superintelligence-android / README.md

raw file 5081 bytes
# superintelligence-android

Fork of [superintelligence (JG2HQZWB/superintelligence)](https://notdouble.com/p/JG2HQZWB/superintelligence) — the same
hands-on LLM agent, ported from a Rust terminal CLI to an **Android app**: Kotlin +
Jetpack Compose, a streaming OpenAI-compatible client, and dialogs instead of
`[Y/n]` prompts.

## What it does

Point the app at any OpenAI-compatible server (llama-server, LiteLLM, vLLM —
anything exposing `/v1/chat/completions` and streaming SSE) and it behaves like
the CLI original:

- **Streams replies** (SSE) with tool-call deltas assembled as they arrive.
- **Tools** the model can call, scoped to the app's private working directory
  (`Android/data/net.kentonc.si/files`):
  - `read_file(path)`
  - `list_dir(path?)`
  - `search(pattern, path?, include?)` — regex walk, skips binaries/`.git`/`target`/…
  - `write_file(path, content)` — **approval dialog**
  - `run_shell(command)` — runs `sh -c` in the working root, 60s timeout — **approval dialog**
- **Image attachments** via the system photo picker (png/jpeg/gif/webp, 20 MB cap).
- **Markdown replies** rendered with a small built-in renderer (headings, lists,
  code fences, blockquotes, inline formatting).
- Approvals: `write_file` / `run_shell` pop a dialog; the tool stays parked
  (a `CompletableDeferred`) until you tap **Run it** / **Decline**. Declines are
  reported back to the model exactly as the CLI does. Settings has an
  auto-approve switch, equivalent to the CLI's `--yes`.

The same guardrails from the Rust port carried over: paths can't escape the
working root, tool output is truncated (16 KB), shell commands time out at 60s,
a tool-budget of 50 rounds per turn, and on any error the turn's messages are
rolled back out of the history.

## Config

Everything else you'd find in `src/config.rs` in the CLI owner is editable in
the app's **Settings** screen (persisted in SharedPreferences): base URL, API
key, model, temperature, max tokens, auto-approve.

Settings default mirrors the CLI (`http://127.0.0.1:8085`, model
`Qwen3.8-27B-GSQ-RCO-IQ3_XXS-mtp.gguf`) — point it at a server on your LAN
instead (Ollama is `http://<ip>:11434`, llama-server is `http://<ip>:8085`).
Cleartext http is allowed on purpose for exactly that. Opening Settings
auto-lists the models the selected server serves — from Ollama's `/api/tags`
(with on-disk sizes) or any OpenAI-compatible `/v1/models` — as a dropdown, so
you never have to type a model name; typing a custom one still works.

## Build

Requires Android SDK (platform 35, build-tools 35) and a JDK 17+:

```sh
cd android && ./gradlew :app:assembleDebug
# -> android/app/build/outputs/apk/debug/app-debug.apk
```

Gradle 8.10.2 + AGP 8.7.3 + Kotlin 2.0.21 + Compose BOM 2024.12.01. A wrapper
is included, so no local Gradle install is needed.

Install on a device:

```sh
adb install android/app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n net.kentonc.si/.MainActivity
```

## Install the APK

A ready-to-install debug APK ships **inside this project's bundle** (releases
tab → "artifacts in the bundle"), extracted under `bin/`. The name embeds the
release version, e.g.:

```sh
tar -xf superintelligence-android.tar.gz bin/superintelligence-android-0.2.3.apk
adb install bin/superintelligence-android-0.2.3.apk
adb shell am start -n net.kentonc.si/.MainActivity
```

It's the standard debug signature (installable directly); versionName matches
the project version on the hub.

## In-app self-update

From **0.2.3 on**, the app checks the hub on launch and shows a deep-update
icon in the top bar whenever `notdouble.com` has a newer release than the
installed build. Tap it: it downloads the new APK into app cache (with an in-bar
progress ring) and launches the system installer. The first update needs the
"allow installs from this app" toggle (Android requires it for anything
sideloaded); the app walks you to it, remember to come back and tap the button
again. After that first grant, updates are one tap with no re-download of
anything.

## Build the Rust original is still here

This fork deliberately kept the original CLI sources untouched — `src/`,
`Cargo.toml`, and `make build` still produce the `si` terminal binary on any
machine. The Android port is a sibling of the CLI, not a replacement of it; both
share the same mental model of tools and approvals.

## Layout

```
android/                     the new thing: the Android app
  app/src/main/java/net/kentonc/si/
    agent/  Agent.kt LlmClient.kt Tools.kt Models.kt Settings.kt    (the port of src/llm.rs + src/tools.rs + src/config.rs)
    ui/     ChatScreen.kt SettingsScreen.kt MarkdownText.kt Theme.kt
    AgentViewModel.kt MainActivity.kt
src/                         the original Rust CLI (unchanged)
```

## Publish to the hub

```sh
make upload      # nd validate && nd upload
```

This directory ships to the hub as `JG2HQZWB/superintelligence-android`
(fork lineage points at `JG2HQZWB/superintelligence`). Build artifacts
(`target/`, Gradle `build/` dirs, APKs) are excluded via `.ndignore`.