@@ -2,12 +2,10 @@ import { Text } from "@components/text";
22import {
33 DEFAULT_CLAUDE_EXECUTION_MODE ,
44 getAvailableModesForAdapter ,
5- getDefaultExecutionModeForAdapter ,
65} from "@posthog/core/sessions/executionModes" ;
76import { resolveCloudComposerModelChange } from "@posthog/core/task-detail/composerModelPolicy" ;
87import {
98 type Adapter ,
10- DEFAULT_CODEX_MODEL ,
119 DEFAULT_GATEWAY_MODEL ,
1210 DEFAULT_REASONING_EFFORT ,
1311 type ExecutionMode ,
@@ -20,17 +18,10 @@ import { LinearGradient } from "expo-linear-gradient";
2018import { Stack , useLocalSearchParams , useRouter } from "expo-router" ;
2119import {
2220 ArrowUp ,
23- BrainIcon ,
2421 CaretDown ,
25- Cpu ,
2622 GithubLogo ,
2723 MicrophoneIcon ,
2824 PaperclipIcon ,
29- PauseIcon ,
30- PencilIcon ,
31- Robot ,
32- ShieldCheck ,
33- Sparkle ,
3425 StopIcon ,
3526} from "phosphor-react-native" ;
3627import { useCallback , useEffect , useState } from "react" ;
@@ -50,6 +41,7 @@ import { useVoiceRecording } from "@/features/chat";
5041import { usePreferencesStore } from "@/features/preferences/stores/preferencesStore" ;
5142import { GitHubConnectionPrompt } from "@/features/tasks/components/GitHubConnectionPrompt" ;
5243import { GitHubLoadNotice } from "@/features/tasks/components/GitHubLoadNotice" ;
44+ import { AgentConfigControls } from "@/features/tasks/composer/AgentConfigControls" ;
5345import { AttachmentSheet } from "@/features/tasks/composer/attachments/AttachmentSheet" ;
5446import { AttachmentsBar } from "@/features/tasks/composer/attachments/AttachmentsBar" ;
5547import { buildCloudPromptBlocks } from "@/features/tasks/composer/attachments/buildCloudPrompt" ;
@@ -60,14 +52,8 @@ import {
6052} from "@/features/tasks/composer/attachments/pickers" ;
6153import type { PendingAttachment } from "@/features/tasks/composer/attachments/types" ;
6254import { DotBackground } from "@/features/tasks/composer/DotBackground" ;
63- import {
64- getComposerModelOptions ,
65- getConfigOptionLabel ,
66- getModelConfigOption ,
67- } from "@/features/tasks/composer/options" ;
68- import { Pill } from "@/features/tasks/composer/Pill" ;
55+ import { getModelConfigOption } from "@/features/tasks/composer/options" ;
6956import { RepositoryPickerInline } from "@/features/tasks/composer/RepositoryPickerInline" ;
70- import { SelectSheet } from "@/features/tasks/composer/SelectSheet" ;
7157import { useCloudTaskConfigOptions } from "@/features/tasks/hooks/useCloudTaskConfigOptions" ;
7258import { useUserIntegrations } from "@/features/tasks/hooks/useUserIntegrations" ;
7359import { useWarmTask } from "@/features/tasks/hooks/useWarmTask" ;
@@ -81,6 +67,7 @@ import type {
8167 CreateTaskOptions ,
8268 RepositorySelection ,
8369} from "@/features/tasks/types" ;
70+ import { buildCloudTaskRunConfig } from "@/features/tasks/utils/cloudTaskRunConfig" ;
8471import {
8572 findRepositoryOption ,
8673 isRepositorySelectionComplete ,
@@ -92,31 +79,12 @@ import { getPostHogApiClient } from "@/lib/posthogApiClient";
9279import { toRgba , useThemeColors } from "@/lib/theme" ;
9380
9481const log = logger . scope ( "task-create" ) ;
95- const SWITCH_ADAPTER_VALUE = "__switch_adapter__" ;
9682const SUGGESTIONS = [
9783 "Create or update my CLAUDE.md file" ,
9884 "Search for a TODO comment and fix it" ,
9985 "Recommend areas to improve our tests" ,
10086] as const ;
10187
102- function modeIcon ( mode : ExecutionMode , color : string , size = 14 ) {
103- switch ( mode ) {
104- case "plan" :
105- return < PauseIcon size = { size } color = { color } weight = "bold" /> ;
106- case "default" :
107- return < PencilIcon size = { size } color = { color } /> ;
108- case "acceptEdits" :
109- return < ShieldCheck size = { size } color = { color } /> ;
110- case "bypassPermissions" :
111- case "full-access" :
112- return < ShieldCheck size = { size } color = { color } weight = "fill" /> ;
113- case "read-only" :
114- return < PauseIcon size = { size } color = { color } /> ;
115- case "auto" :
116- return < Sparkle size = { size } color = { color } weight = "fill" /> ;
117- }
118- }
119-
12088export default function NewTaskScreen ( ) {
12189 const {
12290 prompt : initialPrompt ,
@@ -135,9 +103,7 @@ export default function NewTaskScreen() {
135103 const [ adapter , setAdapter ] = useState < Adapter > ( "claude" ) ;
136104 const { configOptions, hasLiveConfig, isConfigReady } =
137105 useCloudTaskConfigOptions ( adapter ) ;
138- const executionModes = getAvailableModesForAdapter ( adapter ) ;
139106 const modelConfigOption = getModelConfigOption ( configOptions ) ;
140- const mobileModelOptions = getComposerModelOptions ( modelConfigOption ) ;
141107 const {
142108 error,
143109 hasGithubIntegration,
@@ -233,9 +199,6 @@ export default function NewTaskScreen() {
233199 } , [ adapter , hasLiveConfig , model , modelConfigOption , reasoning ] ) ;
234200 const [ creating , setCreating ] = useState ( false ) ;
235201 const [ repoSheetOpen , setRepoSheetOpen ] = useState ( false ) ;
236- const [ modeSheetOpen , setModeSheetOpen ] = useState ( false ) ;
237- const [ modelSheetOpen , setModelSheetOpen ] = useState ( false ) ;
238- const [ reasoningSheetOpen , setReasoningSheetOpen ] = useState ( false ) ;
239202 const [ attachments , setAttachments ] = useState < PendingAttachment [ ] > ( [ ] ) ;
240203 const [ attachmentSheetOpen , setAttachmentSheetOpen ] = useState ( false ) ;
241204
@@ -378,15 +341,9 @@ export default function NewTaskScreen() {
378341 )
379342 : trimmedPrompt ;
380343
381- const supportsReasoning =
382- getReasoningEffortOptions ( adapter , model ) !== null ;
383-
384344 await client . runTaskInCloud ( task . id , undefined , {
385345 pendingUserMessage,
386- adapter,
387- model,
388- reasoningLevel : supportsReasoning ? reasoning : undefined ,
389- initialPermissionMode : mode ,
346+ ...buildCloudTaskRunConfig ( { adapter, mode, model, reasoning } ) ,
390347 autoPublish : usePreferencesStore . getState ( ) . autoPublishCloudRuns ,
391348 rtkEnabled : usePreferencesStore . getState ( ) . rtkEnabledCloud ,
392349 ...( signalReport
@@ -615,51 +572,27 @@ export default function NewTaskScreen() {
615572 paddingRight : 16 ,
616573 } }
617574 >
618- < Pill
619- icon = { modeIcon (
620- mode ,
621- mode === "plan"
622- ? themeColors . accent [ 11 ]
623- : themeColors . gray [ 11 ] ,
624- ) }
625- label = {
626- executionModes . find ( ( option ) => option . id === mode )
627- ?. name ?? mode
628- }
629- accent = { mode === "plan" }
630- onPress = { ( ) => setModeSheetOpen ( true ) }
575+ < AgentConfigControls
576+ adapter = { adapter }
577+ mode = { mode }
578+ model = { model }
579+ reasoning = { reasoning }
580+ configOptions = { configOptions }
581+ onAdapterChange = { setAdapter }
582+ onModeChange = { ( next ) => {
583+ setMode ( next ) ;
584+ usePreferencesStore
585+ . getState ( )
586+ . setLastNewTaskMode ( next ) ;
587+ } }
588+ onModelChange = { setModel }
589+ onReasoningChange = { ( next ) => {
590+ setReasoning ( next ) ;
591+ usePreferencesStore
592+ . getState ( )
593+ . setLastUsedReasoningEffort ( next ) ;
594+ } }
631595 />
632-
633- < Pill
634- icon = {
635- adapter === "codex" ? (
636- < Cpu size = { 14 } color = { themeColors . gray [ 11 ] } />
637- ) : (
638- < Robot size = { 14 } color = { themeColors . gray [ 11 ] } />
639- )
640- }
641- label = {
642- getConfigOptionLabel (
643- modelConfigOption . options ,
644- model ,
645- ) ?? model
646- }
647- onPress = { ( ) => setModelSheetOpen ( true ) }
648- />
649-
650- { showReasoningPill ? (
651- < Pill
652- icon = {
653- < BrainIcon size = { 14 } color = { themeColors . gray [ 11 ] } />
654- }
655- label = {
656- reasoningOptions . find (
657- ( option ) => option . value === reasoning ,
658- ) ?. name ?? reasoning
659- }
660- onPress = { ( ) => setReasoningSheetOpen ( true ) }
661- />
662- ) : null }
663596 </ ScrollView >
664597 { /* Right-edge fade hints that more pills exist when the row
665598 overflows. Non-interactive so taps fall through. */ }
@@ -768,98 +701,6 @@ export default function NewTaskScreen() {
768701 </ Animated . View >
769702 </ View >
770703
771- < SelectSheet
772- open = { modeSheetOpen }
773- title = "Execution mode"
774- value = { mode }
775- onChange = { ( value ) => {
776- const next = value as ExecutionMode ;
777- setMode ( next ) ;
778- usePreferencesStore . getState ( ) . setLastNewTaskMode ( next ) ;
779- } }
780- onClose = { ( ) => setModeSheetOpen ( false ) }
781- options = { executionModes . map ( ( executionMode ) => ( {
782- value : executionMode . id ,
783- label : executionMode . name ,
784- description : executionMode . description ,
785- icon : modeIcon (
786- executionMode . id as ExecutionMode ,
787- executionMode . id === "plan"
788- ? themeColors . accent [ 11 ]
789- : themeColors . gray [ 11 ] ,
790- 16 ,
791- ) ,
792- } ) ) }
793- />
794-
795- < SelectSheet
796- open = { modelSheetOpen }
797- title = "Model"
798- value = { model }
799- onChange = { ( value ) => {
800- if ( value === SWITCH_ADAPTER_VALUE ) {
801- const nextAdapter : Adapter =
802- adapter === "claude" ? "codex" : "claude" ;
803- setAdapter ( nextAdapter ) ;
804- setMode ( getDefaultExecutionModeForAdapter ( nextAdapter ) ) ;
805- setModel (
806- nextAdapter === "codex"
807- ? DEFAULT_CODEX_MODEL
808- : DEFAULT_GATEWAY_MODEL ,
809- ) ;
810- setReasoning ( DEFAULT_REASONING_EFFORT ) ;
811- return ;
812- }
813- const next = resolveCloudComposerModelChange ( {
814- adapter,
815- modelOption : modelConfigOption ,
816- requestedModel : value ,
817- reasoning,
818- } ) ;
819- setModel ( next . model ) ;
820- setReasoning ( next . reasoning ) ;
821- } }
822- onClose = { ( ) => setModelSheetOpen ( false ) }
823- options = { [
824- ...mobileModelOptions . map ( ( modelOption ) => ( {
825- value : modelOption . value ,
826- label : modelOption . label ,
827- description : modelOption . description ,
828- disabled : modelOption . disabled ,
829- icon :
830- adapter === "codex" ? (
831- < Cpu size = { 16 } color = { themeColors . gray [ 11 ] } />
832- ) : (
833- < Robot size = { 16 } color = { themeColors . gray [ 11 ] } />
834- ) ,
835- } ) ) ,
836- {
837- value : SWITCH_ADAPTER_VALUE ,
838- label : `Switch to ${ adapter === "claude" ? "Codex" : "Claude Code" } ` ,
839- description : "Change coding agent" ,
840- disabled : false ,
841- icon : < Cpu size = { 16 } color = { themeColors . accent [ 11 ] } /> ,
842- } ,
843- ] }
844- />
845-
846- < SelectSheet
847- open = { reasoningSheetOpen }
848- title = "Reasoning"
849- value = { reasoning }
850- onChange = { ( value ) => {
851- const next = value as SupportedReasoningEffort ;
852- setReasoning ( next ) ;
853- usePreferencesStore . getState ( ) . setLastUsedReasoningEffort ( next ) ;
854- } }
855- onClose = { ( ) => setReasoningSheetOpen ( false ) }
856- options = { reasoningOptions . map ( ( reasoningLevel ) => ( {
857- value : reasoningLevel . value ,
858- label : reasoningLevel . name ,
859- icon : < BrainIcon size = { 16 } color = { themeColors . gray [ 11 ] } /> ,
860- } ) ) }
861- />
862-
863704 < AttachmentSheet
864705 open = { attachmentSheetOpen }
865706 onClose = { ( ) => setAttachmentSheetOpen ( false ) }
0 commit comments