Attachments were images only. Now any file can be attached: from the file chooser behind the "+" menu, or from Android's share sheet, which the app is now in. An image still goes to the model as a picture; anything else is stored under its own name (`<hex>-<name>`, cleaned by `safe_file_name`) and the Claude driver ends the message with `Attached file: /abs/path`, since the CLI reads files by path and a model cannot be shown a trace. The user-message field is renamed `images` -> `attachments` on both sides, with a serde alias reading the rows written before. A share arrives before anyone has said which session it is for, so it is held in AppRoot with a banner on the list until a session takes it; an open session takes it at once. Unreadable shares are reported beside the composer, not thrown. The tool card crashed the app when opened on a command holding a quoted glob such as `-path '*/.git/*'`: highlights 1.1.0's shell lexer answers `x '*/a/*'` with a span whose end is before its start, and AnnotatedString refuses the range. Such spans are dropped; the library is the place for the fix. The echo driver gains `/bash <command>` so a card with a given command can be produced on the emulator. ui-sandbox.sh's token salvage read the tokens block's close only at a line start, ran past the compact `),],` the server writes, and copied `setups` into the new config twice, which the server then refused. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
116 lines
6.6 KiB
XML
116 lines
6.6 KiB
XML
<?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">
|
|
<!-- Lets the phone's own System Tracing see this app's trace sections
|
|
(Compose's phases, and the composable names runtime-tracing
|
|
adds) in a release build, so a frame cost measured on the real
|
|
device can be attributed. shell="true" limits it to profilers
|
|
run from the shell; it grants nothing to other apps. -->
|
|
<profileable android:shell="true" tools:targetApi="q" />
|
|
<!-- 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>
|
|
<!-- The share sheet: a file, a photo or some text from another app
|
|
lands here and is attached to a session (see Share.kt). Any
|
|
type, because what a session can be handed is the server's
|
|
decision rather than the sheet's. -->
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.SEND" />
|
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<data android:mimeType="*/*" />
|
|
</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>
|