Take ktfmt's defaults for the Kotlin half
The server half went to rustfmt's defaults earlier today; this is the same move for the app, and the same reasoning. Kotlin ships no formatter with the Gradle build, so the question was which to adopt: ktfmt is Kotlin-org owned now (it moved from facebook/ktfmt), is a formatter rather than a configurable linter, and has essentially nothing to tune -- which is what rule 27 is asking for. ktlint's .editorconfig surface is the thing that rule warns against, and detekt is static analysis, whose job Android Lint already does here. One setting, and it is a choice between the tool's own two styles rather than a tuning: kotlinLangStyle() is the 4-space one, which is what this code already was. The 2-space default would have reindented every file to say nothing. ./gradlew :androidApp:ktfmtFormat to apply ./gradlew :androidApp:ktfmtCheck to verify Formatting only. The one thing worth checking by hand was the generated PEM constant, since a leading newline there costs Android's CertificateFactory its preamble sniff and fails at runtime nowhere near the cause: ktfmt moved `.trimMargin()` onto its own line and left the template alone, and the regenerated constant still starts at the opening quotes. Verified after: ktfmtCheck, compileDebugKotlin and lintDebug all pass, and the APK builds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
This commit is contained in:
1 parent
dde5042b12
commit
0c13090d70
16 files changed
+585
-496
No files matched your search
@@ -1,10 +1,10 @@
|
||||
package com.example.aiapp
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
// The REST half of the backend's surface (see server/src/routes.rs for the
|
||||
// table); the SSE half is EventStream.kt. All blocking network calls --
|
||||
@@ -20,13 +20,12 @@ private const val READ_TIMEOUT_MS = 5000
|
||||
class ApiException(message: String, cause: Throwable? = null) : Exception(message, cause)
|
||||
|
||||
/**
|
||||
* Runs one request against the backend, with the pinned TLS setup, the
|
||||
* bearer token, and the failure translation every call needs. [readBody]
|
||||
* gets the connected, already-status-checked connection to read from.
|
||||
* Runs one request against the backend, with the pinned TLS setup, the bearer token, and the
|
||||
* failure translation every call needs. [readBody] gets the connected, already-status-checked
|
||||
* connection to read from.
|
||||
*
|
||||
* @param readTimeoutMs how long to wait on the response body. The SSE
|
||||
* stream doesn't come through here -- an event stream has no bounded
|
||||
* read time (see EventStream.kt).
|
||||
* @param readTimeoutMs how long to wait on the response body. The SSE stream doesn't come through
|
||||
* here -- an event stream has no bounded read time (see EventStream.kt).
|
||||
*/
|
||||
fun <T> requestFromServer(
|
||||
settings: ServerSettings,
|
||||
@@ -64,7 +63,7 @@ fun <T> requestFromServer(
|
||||
detail.isNullOrEmpty() ->
|
||||
"Server returned HTTP ${connection.responseCode} for $path"
|
||||
else -> detail
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
return readBody(connection)
|
||||
@@ -116,15 +115,16 @@ data class SessionSummary(
|
||||
val lastActivity: Double,
|
||||
)
|
||||
|
||||
private fun parseSession(session: JSONObject) = SessionSummary(
|
||||
id = session.getString("id"),
|
||||
provider = session.getString("provider"),
|
||||
title = session.getString("title"),
|
||||
host = session.optString("host").ifEmpty { null },
|
||||
model = session.optString("model").ifEmpty { null },
|
||||
status = session.getString("status"),
|
||||
lastActivity = session.getDouble("lastActivity"),
|
||||
)
|
||||
private fun parseSession(session: JSONObject) =
|
||||
SessionSummary(
|
||||
id = session.getString("id"),
|
||||
provider = session.getString("provider"),
|
||||
title = session.getString("title"),
|
||||
host = session.optString("host").ifEmpty { null },
|
||||
model = session.optString("model").ifEmpty { null },
|
||||
status = session.getString("status"),
|
||||
lastActivity = session.getDouble("lastActivity"),
|
||||
)
|
||||
|
||||
fun fetchSessions(settings: ServerSettings): List<SessionSummary> =
|
||||
requestFromServer(settings, "/sessions") { it.jsonObjects(::parseSession) }
|
||||
@@ -156,8 +156,8 @@ fun fetchHosts(settings: ServerSettings): List<RemoteHost> =
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a session and returns it as the list would show it. [host] is the
|
||||
* name of a configured host, or null to run on the backend machine itself.
|
||||
* Spawns a session and returns it as the list would show it. [host] is the name of a configured
|
||||
* host, or null to run on the backend machine itself.
|
||||
*/
|
||||
fun spawnSession(
|
||||
settings: ServerSettings,
|
||||
@@ -172,12 +172,17 @@ fun spawnSession(
|
||||
settings,
|
||||
"/sessions",
|
||||
method = "POST",
|
||||
jsonBody = JSONObject().put("provider", provider).put("title", title).apply {
|
||||
if (!host.isNullOrBlank()) put("host", host)
|
||||
if (!model.isNullOrBlank()) put("model", model)
|
||||
if (!cwd.isNullOrBlank()) put("cwd", cwd)
|
||||
if (!permissionMode.isNullOrBlank()) put("permissionMode", permissionMode)
|
||||
}.toString(),
|
||||
jsonBody =
|
||||
JSONObject()
|
||||
.put("provider", provider)
|
||||
.put("title", title)
|
||||
.apply {
|
||||
if (!host.isNullOrBlank()) put("host", host)
|
||||
if (!model.isNullOrBlank()) put("model", model)
|
||||
if (!cwd.isNullOrBlank()) put("cwd", cwd)
|
||||
if (!permissionMode.isNullOrBlank()) put("permissionMode", permissionMode)
|
||||
}
|
||||
.toString(),
|
||||
readTimeoutMs = 30000,
|
||||
) { connection ->
|
||||
parseSession(connection.jsonObject())
|
||||
@@ -193,10 +198,11 @@ fun sendMessage(
|
||||
settings,
|
||||
"/sessions/$sessionId/message",
|
||||
method = "POST",
|
||||
jsonBody = JSONObject()
|
||||
.put("text", text)
|
||||
.put("attachmentIds", JSONArray(attachmentIds))
|
||||
.toString(),
|
||||
jsonBody =
|
||||
JSONObject()
|
||||
.put("text", text)
|
||||
.put("attachmentIds", JSONArray(attachmentIds))
|
||||
.toString(),
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -208,11 +214,11 @@ fun uploadAttachment(
|
||||
mime: String,
|
||||
): String {
|
||||
val boundary = "----aiapp-${System.currentTimeMillis()}"
|
||||
val head = (
|
||||
"--$boundary\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"image\"\r\n" +
|
||||
"Content-Type: $mime\r\n\r\n"
|
||||
).encodeToByteArray()
|
||||
val head =
|
||||
("--$boundary\r\n" +
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"image\"\r\n" +
|
||||
"Content-Type: $mime\r\n\r\n")
|
||||
.encodeToByteArray()
|
||||
val tail = "\r\n--$boundary--\r\n".encodeToByteArray()
|
||||
return requestFromServer(
|
||||
settings,
|
||||
@@ -254,19 +260,25 @@ fun fetchUsage(settings: ServerSettings): List<UsageSnapshot> =
|
||||
provider = snapshot.getString("provider"),
|
||||
available = snapshot.getBoolean("available"),
|
||||
error = snapshot.optString("error").ifEmpty { null },
|
||||
windows = snapshot.getJSONArray("windows").mapObjects { window ->
|
||||
UsageWindow(
|
||||
label = window.getString("label"),
|
||||
percent = window.getDouble("percent"),
|
||||
resetsAt = window.optString("resetsAt").ifEmpty { null },
|
||||
active = window.getBoolean("active"),
|
||||
)
|
||||
},
|
||||
windows =
|
||||
snapshot.getJSONArray("windows").mapObjects { window ->
|
||||
UsageWindow(
|
||||
label = window.getString("label"),
|
||||
percent = window.getDouble("percent"),
|
||||
resetsAt = window.optString("resetsAt").ifEmpty { null },
|
||||
active = window.getBoolean("active"),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun answerQuestion(settings: ServerSettings, sessionId: String, questionId: String, answer: String) {
|
||||
fun answerQuestion(
|
||||
settings: ServerSettings,
|
||||
sessionId: String,
|
||||
questionId: String,
|
||||
answer: String,
|
||||
) {
|
||||
requestFromServer(
|
||||
settings,
|
||||
"/sessions/$sessionId/answer",
|
||||
|
||||
Reference in new issue
Block a user