diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 75889c32d3..6e01b1c790 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -36,6 +36,15 @@ + + + diff --git a/android/app/src/main/java/com/openai/codex/agent/CreateSessionActivity.kt b/android/app/src/main/java/com/openai/codex/agent/CreateSessionActivity.kt new file mode 100644 index 0000000000..95c9a4cafc --- /dev/null +++ b/android/app/src/main/java/com/openai/codex/agent/CreateSessionActivity.kt @@ -0,0 +1,470 @@ +package com.openai.codex.agent + +import android.app.Activity +import android.app.agent.AgentManager +import android.app.agent.AgentSessionInfo +import android.content.Context +import android.content.Intent +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.EditText +import android.widget.ImageView +import android.widget.Spinner +import android.widget.TextView +import android.widget.Toast +import com.openai.codex.bridge.SessionExecutionSettings +import kotlin.concurrent.thread + +class CreateSessionActivity : Activity() { + companion object { + private const val TAG = "CodexCreateSession" + private const val EXTRA_EXISTING_SESSION_ID = "existingSessionId" + private const val EXTRA_TARGET_PACKAGE = "targetPackage" + private const val EXTRA_LOCK_TARGET = "lockTarget" + private const val EXTRA_INITIAL_MODEL = "initialModel" + private const val EXTRA_INITIAL_REASONING_EFFORT = "initialReasoningEffort" + + fun newSessionIntent( + context: Context, + initialSettings: SessionExecutionSettings, + ): Intent { + return Intent(context, CreateSessionActivity::class.java).apply { + putExtra(EXTRA_INITIAL_MODEL, initialSettings.model) + putExtra(EXTRA_INITIAL_REASONING_EFFORT, initialSettings.reasoningEffort) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + } + + fun existingHomeSessionIntent( + context: Context, + sessionId: String, + targetPackage: String, + initialSettings: SessionExecutionSettings, + ): Intent { + return newSessionIntent(context, initialSettings).apply { + putExtra(EXTRA_EXISTING_SESSION_ID, sessionId) + putExtra(EXTRA_TARGET_PACKAGE, targetPackage) + putExtra(EXTRA_LOCK_TARGET, true) + } + } + } + + private val sessionController by lazy { AgentSessionController(this) } + private var availableModels: List = emptyList() + @Volatile + private var modelsRefreshInFlight = false + private val pendingModelCallbacks = mutableListOf<() -> Unit>() + + private var existingSessionId: String? = null + private var selectedPackage: InstalledApp? = null + private var targetLocked = false + + private lateinit var promptInput: EditText + private lateinit var packageSummary: TextView + private lateinit var packageButton: Button + private lateinit var clearPackageButton: Button + private lateinit var modelSpinner: Spinner + private lateinit var effortSpinner: Spinner + private lateinit var titleView: TextView + private lateinit var statusView: TextView + private lateinit var startButton: Button + + private var selectedReasoningOptions = emptyList() + private lateinit var effortLabelAdapter: ArrayAdapter + private var initialSettings = SessionExecutionSettings.default + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_create_session) + setFinishOnTouchOutside(true) + bindViews() + loadInitialState() + refreshModelsIfNeeded(force = true) + } + + private fun bindViews() { + titleView = findViewById(R.id.create_session_title) + statusView = findViewById(R.id.create_session_status) + promptInput = findViewById(R.id.create_session_prompt) + packageSummary = findViewById(R.id.create_session_target_summary) + packageButton = findViewById(R.id.create_session_pick_target_button) + clearPackageButton = findViewById(R.id.create_session_clear_target_button) + modelSpinner = findViewById(R.id.create_session_model_spinner) + effortSpinner = findViewById(R.id.create_session_effort_spinner) + startButton = findViewById(R.id.create_session_start_button) + + effortLabelAdapter = ArrayAdapter( + this, + android.R.layout.simple_spinner_item, + mutableListOf(), + ).also { + it.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + effortSpinner.adapter = it + } + modelSpinner.adapter = ArrayAdapter( + this, + android.R.layout.simple_spinner_item, + mutableListOf(), + ).also { it.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) } + modelSpinner.onItemSelectedListener = SimpleItemSelectedListener { updateEffortOptions(null) } + + packageButton.setOnClickListener { + showInstalledAppPicker { app -> + selectedPackage = app + updatePackageSummary() + } + } + clearPackageButton.setOnClickListener { + selectedPackage = null + updatePackageSummary() + } + findViewById