@@ -12693,8 +12693,8 @@ func TestActiveServer_WorkspaceContextAndDynamicToolInjection(t *testing.T) {
1269312693 require .Equal (t , database .ChatStatusWaiting , chatResult .Status )
1269412694
1269512695 parts := persistedChatParts (ctx , t , db , chat .ID )
12696- require .Len (t , contextFilePartsForAgent (parts , dbAgent .ID ), 1 )
12697- contextPart := contextFilePartsForAgent (parts , dbAgent .ID )[0 ]
12696+ require .Len (t , allContextFilePartsForAgent (parts , dbAgent .ID ), 1 )
12697+ contextPart := allContextFilePartsForAgent (parts , dbAgent .ID )[0 ]
1269812698 require .Equal (t , "/home/coder/project/AGENTS.md" , contextPart .ContextFilePath )
1269912699 require .Equal (t , contextText , contextPart .ContextFileContent )
1270012700 require .Equal (t , "linux" , contextPart .ContextFileOS )
@@ -12785,7 +12785,7 @@ func TestActiveServer_WorkspaceContextAndDynamicToolInjection(t *testing.T) {
1278512785 require .Equal (t , database .ChatStatusWaiting , secondResult .Status )
1278612786
1278712787 parts := persistedChatParts (ctx , t , db , chat .ID )
12788- require .Len (t , contextFilePartsForAgent (parts , dbAgent .ID ), 1 )
12788+ require .Len (t , allContextFilePartsForAgent (parts , dbAgent .ID ), 1 )
1278912789 require .Equal (t , int32 (1 ), contextConfigCalls .Load ())
1279012790
1279112791 requestsMu .Lock ()
@@ -12796,6 +12796,72 @@ func TestActiveServer_WorkspaceContextAndDynamicToolInjection(t *testing.T) {
1279612796 require .True (t , requestHasSystemSubstring (recorded [len (recorded )- 1 ], contextText ))
1279712797 })
1279812798
12799+ t .Run ("commits marker when selected agent is unreachable" , func (t * testing.T ) {
12800+ t .Parallel ()
12801+
12802+ db , ps := dbtestutil .NewDB (t )
12803+ ctx := testutil .Context (t , testutil .WaitLong )
12804+
12805+ var (
12806+ requestsMu sync.Mutex
12807+ requests []recordedOpenAIRequest
12808+ )
12809+ openAIURL := chattest .NewOpenAI (t , func (req * chattest.OpenAIRequest ) chattest.OpenAIResponse {
12810+ if ! req .Stream {
12811+ return chattest .OpenAINonStreamingResponse ("title" )
12812+ }
12813+
12814+ requestsMu .Lock ()
12815+ requests = append (requests , recordOpenAIRequest (req ))
12816+ requestsMu .Unlock ()
12817+
12818+ return chattest .OpenAIStreamingResponse (
12819+ chattest .OpenAITextChunks ("done" )... ,
12820+ )
12821+ })
12822+
12823+ user , org , model := seedChatDependenciesWithProvider (t , db , "openai-compat" , openAIURL )
12824+ ws , dbAgent := seedWorkspaceWithAgent (t , db , user .ID )
12825+ require .NoError (t , db .SoftDeleteWorkspaceAgentsByWorkspaceID (ctx , ws .ID ))
12826+
12827+ var agentDialCalls atomic.Int32
12828+ server := newActiveTestServer (t , db , ps , func (cfg * chatd.Config ) {
12829+ cfg .AgentConn = func (context.Context , uuid.UUID ) (workspacesdk.AgentConn , func (), error ) {
12830+ agentDialCalls .Add (1 )
12831+ return nil , nil , xerrors .New ("unexpected workspace agent dial" )
12832+ }
12833+ })
12834+
12835+ chat , err := server .CreateChat (ctx , chatd.CreateOptions {
12836+ OrganizationID : org .ID ,
12837+ OwnerID : user .ID ,
12838+ APIKeyID : testAPIKeyID (t , db , user .ID ),
12839+ Title : "workspace-context-agent-unreachable" ,
12840+ ModelConfigID : model .ID ,
12841+ WorkspaceID : uuid.NullUUID {UUID : ws .ID , Valid : true },
12842+ AgentID : uuid.NullUUID {UUID : dbAgent .ID , Valid : true },
12843+ InitialUserContent : []codersdk.ChatMessagePart {
12844+ codersdk .ChatMessageText ("Continue without workspace context." ),
12845+ },
12846+ })
12847+ require .NoError (t , err )
12848+
12849+ chatResult := waitForTerminalChat (ctx , t , db , chat .ID )
12850+ require .Equal (t , database .ChatStatusWaiting , chatResult .Status )
12851+
12852+ parts := persistedChatParts (ctx , t , db , chat .ID )
12853+ markers := contextFileMarkersForAgent (parts , dbAgent .ID )
12854+ require .Len (t , markers , 1 )
12855+ require .Empty (t , markers [0 ].ContextFileContent )
12856+
12857+ requestsMu .Lock ()
12858+ recorded := append ([]recordedOpenAIRequest (nil ), requests ... )
12859+ requestsMu .Unlock ()
12860+ require .Len (t , recorded , 1 , "expected model call after marker commit" )
12861+ require .False (t , requestHasSystemSubstring (recorded [0 ], "Source: " ))
12862+ require .Zero (t , agentDialCalls .Load ())
12863+ })
12864+
1279912865 t .Run ("repersists workspace context after agent changes" , func (t * testing.T ) {
1280012866 t .Parallel ()
1280112867
@@ -12892,8 +12958,8 @@ func TestActiveServer_WorkspaceContextAndDynamicToolInjection(t *testing.T) {
1289212958 require .Equal (t , database .ChatStatusWaiting , secondResult .Status )
1289312959
1289412960 parts := persistedChatParts (ctx , t , db , chat .ID )
12895- require .Len (t , contextFilePartsForAgent (parts , firstAgent .ID ), 1 )
12896- require .Len (t , contextFilePartsForAgent (parts , secondAgent .ID ), 1 )
12961+ require .Len (t , allContextFilePartsForAgent (parts , firstAgent .ID ), 1 )
12962+ require .Len (t , allContextFilePartsForAgent (parts , secondAgent .ID ), 1 )
1289712963
1289812964 requestsMu .Lock ()
1289912965 recorded := append ([]recordedOpenAIRequest (nil ), requests ... )
@@ -12979,7 +13045,7 @@ func persistedChatMessages(
1297913045 return messages
1298013046}
1298113047
12982- func contextFilePartsForAgent (
13048+ func allContextFilePartsForAgent (
1298313049 parts []codersdk.ChatMessagePart ,
1298413050 agentID uuid.UUID ,
1298513051) []codersdk.ChatMessagePart {
@@ -12996,6 +13062,22 @@ func contextFilePartsForAgent(
1299613062 return matched
1299713063}
1299813064
13065+ func contextFileMarkersForAgent (
13066+ parts []codersdk.ChatMessagePart ,
13067+ agentID uuid.UUID ,
13068+ ) []codersdk.ChatMessagePart {
13069+ var matched []codersdk.ChatMessagePart
13070+ for _ , part := range parts {
13071+ if part .Type != codersdk .ChatMessagePartTypeContextFile ||
13072+ ! part .ContextFileAgentID .Valid ||
13073+ part .ContextFileAgentID .UUID != agentID {
13074+ continue
13075+ }
13076+ matched = append (matched , part )
13077+ }
13078+ return matched
13079+ }
13080+
1299913081func requireChatToolPart (
1300013082 t * testing.T ,
1300113083 messages []database.ChatMessage ,
0 commit comments