diff --git a/plugins/agent-workbench/sessions/src/service/AgentSessionLaunchService.kt b/plugins/agent-workbench/sessions/src/service/AgentSessionLaunchService.kt index acba0d23a3f9..533639f23a28 100644 --- a/plugins/agent-workbench/sessions/src/service/AgentSessionLaunchService.kt +++ b/plugins/agent-workbench/sessions/src/service/AgentSessionLaunchService.kt @@ -55,14 +55,12 @@ import com.intellij.platform.ai.agent.sessions.core.providers.AgentInitialMessag import com.intellij.platform.ai.agent.sessions.core.providers.AgentPendingSessionMetadata import com.intellij.platform.ai.agent.sessions.core.providers.AgentPrestartNewSessionLaunchRequest import com.intellij.platform.ai.agent.sessions.core.providers.AgentTerminalPromptDispatch -import com.intellij.platform.ai.agent.sessions.core.providers.AgentPromptProviderOptionTarget import com.intellij.platform.ai.agent.sessions.core.providers.AgentSessionLaunchProfileResolver import com.intellij.platform.ai.agent.sessions.core.providers.AgentSessionProviderDescriptor import com.intellij.platform.ai.agent.sessions.core.providers.AgentSessionProviderUiContributors import com.intellij.platform.ai.agent.sessions.core.providers.AgentSessionProviders import com.intellij.platform.ai.agent.sessions.core.providers.AgentSessionTerminalLaunchSpec import com.intellij.platform.ai.agent.sessions.core.providers.isBlockedForExistingThreadPlanMode -import com.intellij.platform.ai.agent.sessions.core.providers.resolveEffectiveProviderOptionIds import com.intellij.agent.workbench.sessions.statistics.AgentWorkbenchEntryPoint import com.intellij.agent.workbench.sessions.statistics.AgentWorkbenchTargetKind import com.intellij.agent.workbench.sessions.statistics.AgentWorkbenchTelemetry @@ -1290,12 +1288,8 @@ class AgentSessionLaunchService internal constructor( return NewSessionLaunchPreparationResult.Failed(AgentPromptLaunchError.PROVIDER_UNAVAILABLE) } notifyAgentSessionConversationOpened(descriptor) - val staticInitialMessageRequest = initialMessageRequest?.withEffectiveProviderOptions( - descriptor = descriptor, - target = AgentPromptProviderOptionTarget.NEW_TASK, - ) val staticInitialMessagePlan = if (initialMessageRequestBuilder == null) { - staticInitialMessageRequest?.let(descriptor::buildInitialMessagePlan) ?: AgentInitialMessagePlan.EMPTY + initialMessageRequest?.let(descriptor::buildInitialMessagePlan) ?: AgentInitialMessagePlan.EMPTY } else { AgentInitialMessagePlan.EMPTY @@ -1332,11 +1326,7 @@ class AgentSessionLaunchService internal constructor( launchProfileId = launchProfileId, launchTargetId = plannedLaunch.intent.launchTargetId, ) - val effectiveInitialMessageRequest = (initialMessageRequestBuilder?.invoke(preliminaryContext) ?: staticInitialMessageRequest) - ?.withEffectiveProviderOptions( - descriptor = descriptor, - target = AgentPromptProviderOptionTarget.NEW_TASK, - ) + val effectiveInitialMessageRequest = initialMessageRequestBuilder?.invoke(preliminaryContext) ?: initialMessageRequest if (updateGeneralProviderPreferences && descriptor.supportsPromptLaunch) { uiPreferencesState.updateProviderOptionsOnLaunch(provider.value, effectiveInitialMessageRequest) } @@ -1498,10 +1488,7 @@ class AgentSessionLaunchService internal constructor( threadId = targetThreadId, ) ?: return@run reportPromptLaunchResolved(AgentPromptLaunchResult.failure(AgentPromptLaunchError.TARGET_THREAD_NOT_FOUND)) - val effectiveInitialMessageRequest = request.initialMessageRequest.withEffectiveProviderOptions( - descriptor = bridge, - target = AgentPromptProviderOptionTarget.EXISTING_TASK, - ) + val effectiveInitialMessageRequest = request.initialMessageRequest val initialMessagePlan = bridge.buildInitialMessagePlan(effectiveInitialMessageRequest) if (initialMessagePlan.isBlockedForExistingThreadPlanMode(targetThread.activityReport.rowActivity)) { return@run reportPromptLaunchResolved(AgentPromptLaunchResult.failure(AgentPromptLaunchError.TARGET_THREAD_BUSY_FOR_PLAN_MODE)) @@ -1813,18 +1800,6 @@ private fun resolveLaunchProjectDirectory( return resolveAgentWorkbenchProjectDirectory(identityPath = path) } -private fun AgentPromptInitialMessageRequest.withEffectiveProviderOptions( - descriptor: AgentSessionProviderDescriptor, - target: AgentPromptProviderOptionTarget, -): AgentPromptInitialMessageRequest { - val effectiveOptionIds = resolveEffectiveProviderOptionIds( - selectedProvider = descriptor, - selectedOptionIds = providerOptionIds, - target = target, - ) - return if (effectiveOptionIds == providerOptionIds) this else copy(providerOptionIds = effectiveOptionIds) -} - private suspend fun resolvePromptInitialMessageDispatchPlan( normalizedPath: String, thread: AgentSessionThread, diff --git a/plugins/agent-workbench/spec/actions/global-prompt-entry.spec.md b/plugins/agent-workbench/spec/actions/global-prompt-entry.spec.md index edf336b6e5f8..1d900a8c2ab1 100644 --- a/plugins/agent-workbench/spec/actions/global-prompt-entry.spec.md +++ b/plugins/agent-workbench/spec/actions/global-prompt-entry.spec.md @@ -24,7 +24,7 @@ targets: # Global Prompt Entry Status: Draft -Date: 2026-05-27 +Date: 2026-06-30 ## Summary The global prompt opens a project-scoped prompt surface for starting a new task or sending a prompt to an existing loaded task. The surface is normally a popup, but the empty editor state may host a compact inline prompt composer instead of standard empty-state hints. This spec owns popup and inline lifecycle, target mode, validation, keyboard behavior, provider selection, and launcher handoff. Context collection and Add-to-Agent-Context routing are specified separately. @@ -96,9 +96,11 @@ The global prompt opens a project-scoped prompt surface for starting a new task [@test] ../../chat/testSrc/AgentChatFileEditorLifecycleTest.kt [@test] ../../sessions/testSrc/AgentSessionLaunchServiceTest.kt -- Plan mode is available as a compact header icon toggle only when the selected provider exposes the plan-mode option. Its last-used state is stored per provider as provider option preferences, restored on prompt open, sent in the launch payload, and forced off or rejected for busy existing tasks. A typed `/plan` prefix remains prompt text and does not toggle the option. +- Plan mode is available as a compact header icon toggle only when the selected provider exposes the plan-mode option. Its last-used state is stored per provider as provider option preferences, restored on prompt open, sent in the launch payload, and forced off or rejected for busy existing tasks. The prompt UI filters selectable options before submit, but launch service preserves explicit launch-request option ids so providers can resolve capability-dependent behavior. A typed `/plan` prefix remains prompt text and does not toggle the option. [@test] ../../prompt/ui/testSrc/AgentPromptPlanModeDecisionsTest.kt [@test] ../../sessions/testSrc/AgentSessionPromptLauncherBridgeTest.kt + [@test] ../../lib-agent/providers/junie/sessions/testSrc/JunieExistingThreadPromptLaunchIntegrationTest.kt + [@test] ../../lib-agent/providers/junie/sessions/testSrc/JunieNewThreadPromptLaunchIntegrationTest.kt - Codex `NEW_TASK` prompts start through the Codex app-server remote-resume path. Standard prompts start plain app-server turns; Plan prompts do not type `/plan`, and the resumed TUI must visibly enter Plan mode before the prompt starts. An acknowledged no-op `thread/settings/update` without `thread/settings/updated` must not be treated as prompt-send failure. [@test] ../../lib-agent/providers/codex/sessions/testSrc/CodexPlanPromptRealAppServerIntegrationTest.kt