@@ -977,7 +977,7 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
977
977
)
978
978
979
979
// Check if subagent already exists for this devcontainer.
980
- recreateSubAgent := false
980
+ maybeRecreateSubAgent := false
981
981
proc ,injected := api .injectedSubAgentProcs [dc .WorkspaceFolder ]
982
982
if injected {
983
983
if proc .containerID == container .ID && proc .ctx .Err ()== nil {
@@ -992,12 +992,15 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
992
992
logger .Debug (ctx ,"container ID changed, injecting subagent into new container" ,
993
993
slog .F ("old_container_id" ,proc .containerID ),
994
994
)
995
- recreateSubAgent = true
995
+ maybeRecreateSubAgent = true
996
996
}
997
997
998
998
// Container ID changed or the subagent process is not running,
999
999
// stop the existing subagent context to replace it.
1000
1000
proc .stop ()
1001
+ }else {
1002
+ // Set SubAgent defaults.
1003
+ proc .agent .OperatingSystem = "linux" // Assuming Linux for devcontainers.
1001
1004
}
1002
1005
1003
1006
// Prepare the subAgentProcess to be used when running the subagent.
@@ -1090,36 +1093,33 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1090
1093
// logger.Warn(ctx, "set CAP_NET_ADMIN on agent binary failed", slog.Error(err))
1091
1094
// }
1092
1095
1096
+ updatedSubAgent := proc .agent
1097
+
1093
1098
// Detect workspace folder by executing `pwd` in the container.
1094
1099
// NOTE(mafredri): This is a quick and dirty way to detect the
1095
1100
// workspace folder inside the container. In the future we will
1096
1101
// rely more on `devcontainer read-configuration`.
1097
- var pwdBuf bytes.Buffer
1098
- err = api .dccli .Exec (ctx ,dc .WorkspaceFolder ,dc .ConfigPath ,"pwd" , []string {},
1099
- WithExecOutput (& pwdBuf ,io .Discard ),
1100
- WithExecContainerID (container .ID ),
1101
- )
1102
- if err != nil {
1103
- return xerrors .Errorf ("check workspace folder in container: %w" ,err )
1104
- }
1105
- directory := strings .TrimSpace (pwdBuf .String ())
1106
- if directory == "" {
1107
- logger .Warn (ctx ,"detected workspace folder is empty, using default workspace folder" ,
1108
- slog .F ("default_workspace_folder" ,DevcontainerDefaultContainerWorkspaceFolder ),
1102
+ if proc .agent .Directory == "" || maybeRecreateSubAgent {
1103
+ var pwdBuf bytes.Buffer
1104
+ err = api .dccli .Exec (ctx ,dc .WorkspaceFolder ,dc .ConfigPath ,"pwd" , []string {},
1105
+ WithExecOutput (& pwdBuf ,io .Discard ),
1106
+ WithExecContainerID (container .ID ),
1109
1107
)
1110
- directory = DevcontainerDefaultContainerWorkspaceFolder
1111
- }
1112
-
1113
- if proc .agent .ID != uuid .Nil && recreateSubAgent {
1114
- logger .Debug (ctx ,"deleting existing subagent for recreation" ,slog .F ("agent_id" ,proc .agent .ID ))
1115
- client := * api .subAgentClient .Load ()
1116
- err = client .Delete (ctx ,proc .agent .ID )
1117
1108
if err != nil {
1118
- return xerrors .Errorf ("delete existing subagent failed: %w" ,err )
1109
+ return xerrors .Errorf ("check workspace folder in container: %w" ,err )
1110
+ }
1111
+ directory := strings .TrimSpace (pwdBuf .String ())
1112
+ if directory == "" {
1113
+ logger .Warn (ctx ,"detected workspace folder is empty, using default workspace folder" ,
1114
+ slog .F ("default_workspace_folder" ,DevcontainerDefaultContainerWorkspaceFolder ),
1115
+ )
1116
+ directory = DevcontainerDefaultContainerWorkspaceFolder
1119
1117
}
1120
- proc .agent = SubAgent {}
1118
+
1119
+ updatedSubAgent .Directory = directory
1121
1120
}
1122
- if proc .agent .ID == uuid .Nil {
1121
+
1122
+ if maybeRecreateSubAgent {
1123
1123
displayAppsMap := map [codersdk.DisplayApp ]bool {
1124
1124
// NOTE(DanielleMaywood):
1125
1125
// We use the same defaults here as set in terraform-provider-coder.
@@ -1138,6 +1138,9 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1138
1138
1139
1139
for _ ,customization := range coderCustomization {
1140
1140
for app ,enabled := range customization .DisplayApps {
1141
+ if _ ,ok := displayAppsMap [app ];! ok {
1142
+ continue // Ignore unknown display apps.
1143
+ }
1141
1144
displayAppsMap [app ]= enabled
1142
1145
}
1143
1146
}
@@ -1149,24 +1152,37 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
1149
1152
displayApps = append (displayApps ,app )
1150
1153
}
1151
1154
}
1155
+ slices .Sort (displayApps )
1156
+
1157
+ updatedSubAgent .Name = dc .Name
1158
+ updatedSubAgent .DisplayApps = displayApps
1159
+ }
1160
+
1161
+ recreateSubAgent := maybeRecreateSubAgent && ! proc .agent .Equal (updatedSubAgent )
1162
+ if recreateSubAgent {
1163
+ logger .Debug (ctx ,"deleting existing subagent for recreation" ,slog .F ("agent_id" ,proc .agent .ID ))
1164
+ client := * api .subAgentClient .Load ()
1165
+ err = client .Delete (ctx ,proc .agent .ID )
1166
+ if err != nil {
1167
+ return xerrors .Errorf ("delete existing subagent failed: %w" ,err )
1168
+ }
1169
+ proc .agent = SubAgent {}// In case of error, make sure this is cleared.
1170
+
1171
+ // Reset fields that are not part of the request.
1172
+ updatedSubAgent .ID = uuid .Nil
1173
+ updatedSubAgent .AuthToken = uuid .Nil
1152
1174
1153
1175
logger .Debug (ctx ,"creating new subagent" ,
1154
- slog .F ("directory" ,directory ),
1155
- slog .F ("display_apps" ,displayApps ),
1176
+ slog .F ("directory" ,updatedSubAgent . Directory ),
1177
+ slog .F ("display_apps" ,updatedSubAgent . DisplayApps ),
1156
1178
)
1157
1179
1158
1180
// Create new subagent record in the database to receive the auth token.
1159
- client := * api .subAgentClient .Load ()
1160
- proc .agent ,err = client .Create (ctx ,SubAgent {
1161
- Name :dc .Name ,
1162
- Directory :directory ,
1163
- OperatingSystem :"linux" ,// Assuming Linux for devcontainers.
1164
- Architecture :arch ,
1165
- DisplayApps :displayApps ,
1166
- })
1181
+ newSubAgent ,err := client .Create (ctx ,updatedSubAgent )
1167
1182
if err != nil {
1168
1183
return xerrors .Errorf ("create subagent failed: %w" ,err )
1169
1184
}
1185
+ proc .agent = newSubAgent
1170
1186
1171
1187
logger .Info (ctx ,"created new subagent" ,slog .F ("agent_id" ,proc .agent .ID ))
1172
1188
}