11import type {
2+ Template ,
23Workspace ,
34WorkspaceAgent ,
45WorkspaceAgentDevcontainer ,
@@ -30,12 +31,16 @@ import {
3031} from "./SSHButton/SSHButton" ;
3132import { TerminalLink } from "./TerminalLink/TerminalLink" ;
3233import { VSCodeDevContainerButton } from "./VSCodeDevContainerButton/VSCodeDevContainerButton" ;
34+ import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility" ;
35+ import { useProxy } from "contexts/ProxyContext" ;
36+ import { PortForwardButton } from "./PortForwardButton" ;
3337
3438type AgentDevcontainerCardProps = {
3539parentAgent :WorkspaceAgent ;
3640subAgents :WorkspaceAgent [ ] ;
3741devcontainer :WorkspaceAgentDevcontainer ;
3842workspace :Workspace ;
43+ template :Template ;
3944wildcardHostname :string ;
4045} ;
4146
@@ -44,10 +49,13 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
4449subAgents,
4550devcontainer,
4651workspace,
52+ template,
4753wildcardHostname,
4854} ) => {
55+ const { browser_only} = useFeatureVisibility ( ) ;
56+ const { proxy} = useProxy ( ) ;
57+
4958const [ isRecreating , setIsRecreating ] = useState ( false ) ;
50- const [ subAgent , setSubAgent ] = useState < WorkspaceAgent | null > ( null ) ;
5159
5260const handleRecreateDevcontainer = async ( ) => {
5361setIsRecreating ( true ) ;
@@ -83,24 +91,24 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
8391}
8492} ;
8593
94+ const subAgent = subAgents . find ( ( sub ) => sub . id === devcontainer . agent ?. id ) ;
95+ const shouldDisplaySubAgentApps =
96+ subAgent ?. status === "connected" || subAgent ?. status === "connecting" ;
97+
8698// If the devcontainer is starting, reflect this in the recreate button.
8799useEffect ( ( ) => {
100+ console . log (
101+ "Devcontainer status:" ,
102+ devcontainer . status ,
103+ "Sub agent status:" ,
104+ subAgent ?. status ,
105+ ) ;
88106if ( devcontainer . status === "starting" ) {
89107setIsRecreating ( true ) ;
90108} else {
91109setIsRecreating ( false ) ;
92110}
93- } , [ devcontainer . id , devcontainer . status ] ) ;
94-
95- const shouldDisplayAgentApps =
96- subAgent ?. status === "connected" || subAgent ?. status === "connecting" ;
97-
98- // Woot! We have a sub agent, so we can display the forwarded ports.
99- useEffect ( ( ) => {
100- setSubAgent (
101- subAgents . find ( ( sub ) => sub . id === devcontainer . agent ?. id ) || null ,
102- ) ;
103- } , [ subAgents , devcontainer . agent ?. id ] ) ;
111+ } , [ devcontainer ] ) ;
104112
105113return (
106114< section
@@ -148,26 +156,41 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
148156Recreate
149157</ Button >
150158
151- { subAgent && subAgent . display_apps . includes ( "ssh_helper" ) && (
152- < AgentSSHButton
153- workspaceName = { workspace . name }
154- agentName = { subAgent . name }
155- workspaceOwnerUsername = { workspace . owner_name }
156- />
157- ) }
159+ { shouldDisplaySubAgentApps &&
160+ ! browser_only &&
161+ // TODO(mafredri): We could use subAgent display apps here but we currently set none.
162+ parentAgent . display_apps . includes ( "ssh_helper" ) && (
163+ < AgentSSHButton
164+ workspaceName = { workspace . name }
165+ agentName = { subAgent . name }
166+ workspaceOwnerUsername = { workspace . owner_name }
167+ />
168+ ) }
169+
170+ { shouldDisplaySubAgentApps &&
171+ proxy . preferredWildcardHostname === "" &&
172+ // TODO(mafredri): We could use subAgent display apps here but we currently set none.
173+ parentAgent . display_apps . includes ( "port_forwarding_helper" ) && (
174+ < PortForwardButton
175+ host = { proxy . preferredWildcardHostname }
176+ workspace = { workspace }
177+ agent = { subAgent }
178+ template = { template }
179+ />
180+ ) }
158181</ div >
159182</ header >
160183
161- { subAgent && devcontainer . container && (
184+ { shouldDisplaySubAgentApps && devcontainer . container && (
162185< >
163186< h4 className = "m-0 text-xl font-semibold mb-2" > Forwarded ports</ h4 >
164187< div className = "flex gap-4 flex-wrap mt-4" >
165188< VSCodeDevContainerButton
166189userName = { workspace . owner_name }
167190workspaceName = { workspace . name }
168191devContainerName = { devcontainer . container . name }
169- devContainerFolder = { subAgent . directory ?? "" } // This will always be set.
170- displayApps = { subAgent . display_apps }
192+ devContainerFolder = { subAgent . directory ?? "/ " } // This will always be set on subagents but provide fallback anyway .
193+ displayApps = { parentAgent . display_apps } // TODO(mafredri): We could use subAgent display apps here but we currently set none.
171194agentName = { parentAgent . name }
172195/>
173196