Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This changelog tracks **Minis for Android** as an independently maintained Andro
- `android-shizuku-cli` is now `android-root-cli`: the same subcommands and JSON, run as root through `su`. Its Agent permission switch carries over.
- The virtual screen runs in a root service (libsu) instead of a Shizuku UserService. Run its compatibility check once more to switch it back on.
- Accessibility repair, clearing restricted settings and one-tap authorize use Root; Settings > System has a Root page in place of "Root & Shizuku", and the readiness checklist no longer lists Shizuku.
- Fast Mode works for GPT models again on the Responses path (Codex login and Responses relays): with the toggle on, requests carry `service_tier: "priority"`, as OpenMinis 1.14 does. A change that kept only the xAI case had turned the toggle into a no-op for GPT.

## 0.0.2 — 2026-10-10

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,19 @@ internal fun OpenAIProvider.buildResponsesAPIBody(
// through, so no isOAuth narrowing. Ineligible upstreams ignore the
// field or silently downgrade (receipt visible via the
// response.completed service_tier log).
//
// [T-android-xai-priority] The per-instance (xAI) tier is resolved first and the
// gpt-family rule only fills a missing key, so neither clobbers the other. The two
// gates are disjoint today: that toggle is xAI-only and xAI never reaches this builder.
// The gpt-family rule had been replaced by the xAI call alone, which made Fast Mode a
// silent no-op for every GPT model (OpenMinis 1.14 keeps both).
resolvedServiceTier()?.let { body.put("service_tier", it) }
if (!body.has("service_tier") &&
com.openminis.app.data.FastModePrefs.isEnabled() &&
model.id.contains("gpt", ignoreCase = true)
) {
body.put("service_tier", "priority")
}

if (systemPrompt != null) {
body.put("instructions", systemPrompt)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.openminis.app.provider

import com.openminis.app.data.FastModePrefs
import com.openminis.app.data.model.LLMMessage
import com.openminis.app.data.model.LLMModel
import com.openminis.app.provider.openai.OpenAIProvider
import com.openminis.app.provider.openai.buildRequestBody
import com.openminis.app.provider.openai.buildRequestBody
import com.openminis.app.provider.openai.buildResponsesAPIBody
import org.json.JSONObject
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Test

/**
* [T-codex-fast-mode] Fast Mode on the Responses path for GPT models.
*
* The Responses builder sends `service_tier: "priority"` when the app-level toggle is on and
* the model is a gpt-family model (OpenMinis 1.14 behaviour). It had been replaced by the
* xAI per-instance call alone, so the toggle did nothing for GPT. xAI's own gate is covered
* by [XAIPriorityProcessingTest].
*/
class CodexFastModeTest {

@After
fun tearDown() {
FastModePrefs.setCachedEnabledForTest(false)
}

private val history = listOf(LLMMessage(LLMMessage.Role.USER, "hello"))

private fun provider(modelId: String, useResponsesAPI: Boolean = true) = OpenAIProvider(
apiKey = "test-key",
model = LLMModel(id = modelId, displayName = modelId, provider = "OpenAI"),
basePath = "https://example.invalid/v1",
useResponsesAPI = useResponsesAPI,
)

private fun responsesBody(modelId: String, fastMode: Boolean): JSONObject {
FastModePrefs.setCachedEnabledForTest(fastMode)
return provider(modelId).buildResponsesAPIBody(
messages = history,
systemPrompt = null,
maxTokens = 1024,
stream = false,
)
}

@Test
fun `a gpt model on the Responses path carries priority when Fast Mode is on`() {
assertEquals("priority", responsesBody("gpt-6-luna", fastMode = true).getString("service_tier"))
}

@Test
fun `the tier is absent when Fast Mode is off`() {
assertFalse(responsesBody("gpt-6-luna", fastMode = false).has("service_tier"))
}

@Test
fun `a model outside the gpt family never carries the tier`() {
assertFalse(
"service_tier leaked into a non-GPT model's Responses body",
responsesBody("deepseek-v4-pro", fastMode = true).has("service_tier"),
)
}

@Test
fun `Chat Completions for a gpt model does not carry the tier`() {
FastModePrefs.setCachedEnabledForTest(true)
val body = provider("gpt-6-luna", useResponsesAPI = false).buildRequestBody(
messages = history,
systemPrompt = null,
maxTokens = 1024,
stream = false,
temperature = null,
imageParts = emptyList(),
)
assertFalse(
"the Chat Completions body only carries the tier for an eligible (xAI) instance",
body.has("service_tier"),
)
}
}
Loading