ai-app: a phone interface to Claude Code and llama.cpp sessions
A Rust backend that owns the sessions and an Android app that reads them. The server spawns and adopts CLI processes, normalises everything they emit into one event model, keeps the transcript, and serves it over pinned TLS on a WireGuard interface; the phone streams that, replies, sends images, and imports conversations the machine already has. `AGENTS.md` is the working guide -- what runs where, what has been measured, and the faults that were expensive to find. `PLAN.md` is the design record. History before this point was squashed away. It was a personal project's running commentary and carried a name and a couple of machine paths that have no business in a public repository; the tree is what mattered and the tree is here.
This commit is contained in:
commit
b172c464ea
100 files changed
+31795
No files matched your search
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- Android 17 (API 37) made Local Network Protection mandatory: an app
|
||||
targeting 37+ needs this runtime permission to reach *any* local
|
||||
network address, including a plain socket to a LAN IP literal.
|
||||
Without it the traffic is silently dropped, surfacing only as a
|
||||
connect timeout. See MainActivity.kt's runtime request, and
|
||||
dev-updater's manifest for the full story. -->
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
|
||||
|
||||
<!-- Telling somebody a session wants them. POST_NOTIFICATIONS is a
|
||||
runtime permission from Android 13; the foreground-service pair
|
||||
below is what lets the connection outlive the app being closed,
|
||||
which is the entire point (see Notifications.kt). -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
|
||||
<!-- tools:ignore MissingApplicationIcon: there is no icon yet, and
|
||||
that is a decision rather than an oversight. An app with no icon
|
||||
of its own is obvious to anyone who opens a launcher, so the
|
||||
warning tells nobody here anything they cannot already see, and
|
||||
the fix is a judgement about how this app should look. Drop this
|
||||
suppression when a real icon lands. -->
|
||||
<application
|
||||
android:label="AI Sessions"
|
||||
android:allowBackup="true"
|
||||
android:theme="@android:style/Theme.Material.Light.NoActionBar"
|
||||
tools:ignore="MissingApplicationIcon">
|
||||
<!-- adjustResize (not the system's default pan): the layout handles
|
||||
the keyboard itself via imePadding(), so the window must resize
|
||||
rather than slide the top bar off screen. -->
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:theme="@android:style/Theme.Material.Light.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- Enrollment: the server prints its aiapp://enroll QR to the
|
||||
terminal. This intent filter is the fallback path for a
|
||||
camera app that redirects a scanned aiapp:// URI here
|
||||
directly; the Settings screen's own "Scan QR code" button
|
||||
(zxing-android-embedded) is the primary path and needs no
|
||||
filter, since it decodes the QR itself and hands the URI
|
||||
to parseEnrollmentUri in-process. -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="aiapp" android:host="enroll" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- specialUse rather than dataSync, which is the type this looks
|
||||
like: Android 15 caps dataSync at six hours a day, and a
|
||||
connection that stops listening after six hours is one that
|
||||
misses the overnight run it exists for. The subtype below is
|
||||
the reason string that type requires. -->
|
||||
<service
|
||||
android:name=".NotificationService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<property
|
||||
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="Holds one connection to the user's own backend so a session
|
||||
that needs an answer can be reported while the app is closed. There is no
|
||||
push service: the backend is reachable only over the user's WireGuard
|
||||
tunnel and never talks to a third party." />
|
||||
</service>
|
||||
|
||||
<!-- The scanner behind Settings' "Scan QR code". Declared here so
|
||||
it can drop the library CaptureActivity's landscape pin: the
|
||||
code being scanned is usually on a monitor in front of someone
|
||||
holding the phone upright. zxing_CaptureTheme is the library's
|
||||
own fullscreen theme, which is all the activity needs. -->
|
||||
<!-- tools:ignore DiscouragedApi: lint flags every fixed
|
||||
screenOrientation, because Android 16 ignores most of them.
|
||||
This one is not a pin but its removal. fullSensor is what
|
||||
drops the library's landscape lock, so the activity follows
|
||||
the phone rather than asking anyone to turn it, and where the
|
||||
platform ignores the attribute the behaviour is the one this
|
||||
asked for anyway. Scoped to this activity, so a genuine pin
|
||||
elsewhere would still be reported. -->
|
||||
<activity
|
||||
android:name="com.example.wgapplink.EnrollmentScanActivity"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:screenOrientation="fullSensor"
|
||||
android:stateNotNeeded="true"
|
||||
android:theme="@style/zxing_CaptureTheme"
|
||||
android:windowSoftInputMode="stateAlwaysHidden"
|
||||
tools:ignore="DiscouragedApi" />
|
||||
</application>
|
||||
</manifest>
|
||||
Reference in new issue
Block a user