@@ -72,16 +72,17 @@ type API struct {
72
72
configFileModifiedTimes map [string ]time.Time // By config file path.
73
73
recreateSuccessTimes map [string ]time.Time // By workspace folder.
74
74
recreateErrorTimes map [string ]time.Time // By workspace folder.
75
- injectedSubAgentProcs map [string ]subAgentProcess // By container ID .
75
+ injectedSubAgentProcs map [string ]subAgentProcess // By workspace folder .
76
76
asyncWg sync.WaitGroup
77
77
78
78
devcontainerLogSourceIDs map [string ]uuid.UUID // By workspace folder.
79
79
}
80
80
81
81
type subAgentProcess struct {
82
- agent SubAgent
83
- ctx context.Context
84
- stop context.CancelFunc
82
+ agent SubAgent
83
+ containerID string
84
+ ctx context.Context
85
+ stop context.CancelFunc
85
86
}
86
87
87
88
// Option is a functional option for API.
@@ -586,7 +587,11 @@ func (api *API) processUpdatedContainersLocked(ctx context.Context, updated code
586
587
dc .Dirty = true
587
588
}
588
589
589
- if _ , injected := api .injectedSubAgentProcs [dc .Container .ID ]; ! injected && dc .Status == codersdk .WorkspaceAgentDevcontainerStatusRunning {
590
+ proc , injected := api .injectedSubAgentProcs [dc .WorkspaceFolder ]
591
+ if injected && proc .containerID != dc .Container .ID {
592
+ injected = false // The container ID changed, we need to re-inject.
593
+ }
594
+ if ! injected && dc .Status == codersdk .WorkspaceAgentDevcontainerStatusRunning {
590
595
err := api .injectSubAgentIntoContainerLocked (ctx , dc )
591
596
if err != nil {
592
597
logger .Error (ctx , "inject subagent into container failed" , slog .Error (err ))
@@ -660,10 +665,22 @@ func (api *API) getContainers() (codersdk.WorkspaceAgentListContainersResponse,
660
665
if len (api .knownDevcontainers ) > 0 {
661
666
devcontainers = make ([]codersdk.WorkspaceAgentDevcontainer , 0 , len (api .knownDevcontainers ))
662
667
for _ , dc := range api .knownDevcontainers {
668
+ // Include the agent if it's been created (we're iterating over
669
+ // copies, so mutating is fine).
670
+ if dc .Container != nil {
671
+ if proc := api .injectedSubAgentProcs [dc .WorkspaceFolder ]; proc .agent .ID != uuid .Nil && proc .containerID == dc .Container .ID {
672
+ dc .Agent = & codersdk.WorkspaceAgentDevcontainerAgent {
673
+ ID : proc .agent .ID ,
674
+ Name : proc .agent .Name ,
675
+ Directory : proc .agent .Directory ,
676
+ }
677
+ }
678
+ }
679
+
663
680
devcontainers = append (devcontainers , dc )
664
681
}
665
682
slices .SortFunc (devcontainers , func (a , b codersdk.WorkspaceAgentDevcontainer ) int {
666
- return strings .Compare (a .ID . String () , b .ID . String () )
683
+ return strings .Compare (a .Name , b .Name )
667
684
})
668
685
}
669
686
@@ -975,9 +992,25 @@ func (api *API) injectSubAgentIntoContainerLocked(ctx context.Context, dc coders
975
992
return xerrors .New ("container is nil, cannot inject subagent" )
976
993
}
977
994
995
+ logger := api .logger .With (
996
+ slog .F ("devcontainer_id" , dc .ID ),
997
+ slog .F ("devcontainer_name" , dc .Name ),
998
+ slog .F ("workspace_folder" , dc .WorkspaceFolder ),
999
+ slog .F ("config_path" , dc .ConfigPath ),
1000
+ slog .F ("container_id" , container .ID ),
1001
+ slog .F ("container_name" , container .FriendlyName ),
1002
+ )
1003
+
978
1004
// Skip if subagent already exists for this container.
979
- if _ , injected := api .injectedSubAgentProcs [container .ID ]; injected || api .closed {
980
- return nil
1005
+ if proc , injected := api .injectedSubAgentProcs [dc .WorkspaceFolder ]; injected || api .closed {
1006
+ if proc .containerID == container .ID {
1007
+ return nil
1008
+ }
1009
+
1010
+ // If the subagent is already injected but the container ID has
1011
+ // changed, we need to inject it into the new container.
1012
+ logger .Debug (ctx , "injecting subagent into new container" )
1013
+ proc .stop ()
981
1014
}
982
1015
983
1016
// Mark subagent as being injected immediately with a placeholder.
@@ -1010,13 +1043,6 @@ func (api *API) injectSubAgentIntoContainerLocked(ctx context.Context, dc coders
1010
1043
api .mu .Unlock ()
1011
1044
defer api .mu .Lock () // Re-lock.
1012
1045
1013
- logger := api .logger .With (
1014
- slog .F ("devcontainer_id" , dc .ID ),
1015
- slog .F ("devcontainer_name" , dc .Name ),
1016
- slog .F ("workspace_folder" , dc .WorkspaceFolder ),
1017
- slog .F ("config_path" , dc .ConfigPath ),
1018
- )
1019
-
1020
1046
arch , err := api .ccli .DetectArchitecture (ctx , container .ID )
1021
1047
if err != nil {
1022
1048
return xerrors .Errorf ("detect architecture: %w" , err )
@@ -1176,7 +1202,9 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1176
1202
}
1177
1203
1178
1204
api .mu .Lock ()
1179
- delete (api .injectedSubAgentProcs , container .ID )
1205
+ if api .injectedSubAgentProcs [dc .WorkspaceFolder ].containerID == container .ID {
1206
+ delete (api .injectedSubAgentProcs , dc .WorkspaceFolder )
1207
+ }
1180
1208
api .mu .Unlock ()
1181
1209
1182
1210
logger .Debug (ctx , "agent process cleanup complete" )
@@ -1191,10 +1219,11 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1191
1219
return
1192
1220
}
1193
1221
// Update the placeholder with a valid subagent, context and stop.
1194
- api .injectedSubAgentProcs [container .ID ] = subAgentProcess {
1195
- agent : agent ,
1196
- ctx : agentCtx ,
1197
- stop : agentStop ,
1222
+ api .injectedSubAgentProcs [dc .WorkspaceFolder ] = subAgentProcess {
1223
+ agent : agent ,
1224
+ containerID : container .ID ,
1225
+ ctx : agentCtx ,
1226
+ stop : agentStop ,
1198
1227
}
1199
1228
api .mu .Unlock ()
1200
1229
@@ -1226,7 +1255,11 @@ func (api *API) Close() error {
1226
1255
api .closed = true
1227
1256
1228
1257
for _ , proc := range api .injectedSubAgentProcs {
1229
- api .logger .Debug (api .ctx , "canceling subagent process" , slog .F ("agent_name" , proc .agent .Name ), slog .F ("agent_id" , proc .agent .ID ))
1258
+ api .logger .Debug (api .ctx , "canceling subagent process" ,
1259
+ slog .F ("agent_name" , proc .agent .Name ),
1260
+ slog .F ("agent_id" , proc .agent .ID ),
1261
+ slog .F ("container_id" , proc .containerID ),
1262
+ )
1230
1263
proc .stop ()
1231
1264
}
1232
1265
0 commit comments