@@ -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 )
@@ -1145,7 +1171,9 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1145
1171
}
1146
1172
1147
1173
api .mu .Lock ()
1148
- delete (api .injectedSubAgentProcs , container .ID )
1174
+ if api .injectedSubAgentProcs [dc .WorkspaceFolder ].containerID == container .ID {
1175
+ delete (api .injectedSubAgentProcs , dc .WorkspaceFolder )
1176
+ }
1149
1177
api .mu .Unlock ()
1150
1178
1151
1179
logger .Debug (ctx , "agent process cleanup complete" )
@@ -1160,10 +1188,11 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1160
1188
return
1161
1189
}
1162
1190
// Update the placeholder with a valid subagent, context and stop.
1163
- api .injectedSubAgentProcs [container .ID ] = subAgentProcess {
1164
- agent : agent ,
1165
- ctx : agentCtx ,
1166
- stop : agentStop ,
1191
+ api .injectedSubAgentProcs [dc .WorkspaceFolder ] = subAgentProcess {
1192
+ agent : agent ,
1193
+ containerID : container .ID ,
1194
+ ctx : agentCtx ,
1195
+ stop : agentStop ,
1167
1196
}
1168
1197
api .mu .Unlock ()
1169
1198
@@ -1195,7 +1224,11 @@ func (api *API) Close() error {
1195
1224
api .closed = true
1196
1225
1197
1226
for _ , proc := range api .injectedSubAgentProcs {
1198
- api .logger .Debug (api .ctx , "canceling subagent process" , slog .F ("agent_name" , proc .agent .Name ), slog .F ("agent_id" , proc .agent .ID ))
1227
+ api .logger .Debug (api .ctx , "canceling subagent process" ,
1228
+ slog .F ("agent_name" , proc .agent .Name ),
1229
+ slog .F ("agent_id" , proc .agent .ID ),
1230
+ slog .F ("container_id" , proc .containerID ),
1231
+ )
1199
1232
proc .stop ()
1200
1233
}
1201
1234
0 commit comments