@@ -3,7 +3,7 @@ import { Workspace, WorkspaceAgent, WorkspaceAgentTask } from "coder/site/src/ap
3
3
import { EventSource } from "eventsource"
4
4
import * as path from "path"
5
5
import * as vscode from "vscode"
6
- import { createStreamingFetchAdapter , getAITasksForWorkspace } from "./api"
6
+ import { createStreamingFetchAdapter } from "./api"
7
7
import {
8
8
AgentMetadataEvent ,
9
9
AgentMetadataEventSchemaArray ,
@@ -147,29 +147,28 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
147
147
} )
148
148
149
149
// Create tree items for each workspace
150
- const workspaceTreeItems = await Promise . all ( resp . workspaces . map ( async ( workspace ) => {
151
- const workspaceTreeItem = new WorkspaceTreeItem (
152
- workspace ,
153
- this . getWorkspacesQuery === WorkspaceQuery . All ,
154
- showMetadata
155
- )
156
-
157
- // Fetch AI tasks for the workspace
158
- try {
159
- // Create a dummy emitter for logs
160
- const emitter = new vscode . EventEmitter < string > ( )
161
- const aiTasks = await getAITasksForWorkspace ( restClient , emitter , workspace )
162
- workspaceTreeItem . aiTasks = aiTasks
163
- this . storage . writeToCoderOutputChannel ( aiTasks . length . toString ( ) )
164
- console . log ( aiTasks . length . toString ( ) )
165
- } catch ( error ) {
166
- // Log the error but continue - we don't want to fail the whole tree if AI tasks fail
167
- this . storage . writeToCoderOutputChannel ( `Failed to fetch AI tasks for workspace${ workspace . name } :${ errToStr ( error , "unknown error" ) } ` )
168
-
169
- }
170
-
171
- return workspaceTreeItem
172
- } ) )
150
+ const workspaceTreeItems = await Promise . all (
151
+ resp . workspaces . map ( async ( workspace ) => {
152
+ const workspaceTreeItem = new WorkspaceTreeItem (
153
+ workspace ,
154
+ this . getWorkspacesQuery === WorkspaceQuery . All ,
155
+ showMetadata ,
156
+ )
157
+
158
+ // Fetch AI tasks for the workspace
159
+ try {
160
+ // Create a dummy emitter for logs
161
+ const emitter = new vscode . EventEmitter < string > ( )
162
+ } catch ( error ) {
163
+ // Log the error but continue - we don't want to fail the whole tree if AI tasks fail
164
+ this . storage . writeToCoderOutputChannel (
165
+ `Failed to fetch AI tasks for workspace${ workspace . name } :${ errToStr ( error , "unknown error" ) } ` ,
166
+ )
167
+ }
168
+
169
+ return workspaceTreeItem
170
+ } ) ,
171
+ )
173
172
174
173
return workspaceTreeItems
175
174
}
@@ -230,24 +229,25 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
230
229
const agentTreeItems = agents . map (
231
230
( agent ) => new AgentTreeItem ( agent , element . workspaceOwner , element . workspaceName , element . watchMetadata ) ,
232
231
)
233
-
234
- // Add AI task items to the workspace children if there are any
235
- const aiTaskItems = element . aiTasks . map ( task => new AITaskTreeItem ( task ) )
236
-
237
- // If there are AI tasks, add them at the beginning of the list
238
- if ( aiTaskItems . length == 0 ) {
239
- return Promise . resolve ( agentTreeItems )
240
- }
241
-
242
- // Return AI task items first, then a separator, then agent items
243
- return Promise . resolve ( [ ...aiTaskItems , ...agentTreeItems ] )
232
+
233
+ return Promise . resolve ( agentTreeItems )
244
234
} else if ( element instanceof AgentTreeItem ) {
245
235
const watcher = this . agentWatchers [ element . agent . id ]
246
236
if ( watcher ?. error ) {
247
237
return Promise . resolve ( [ new ErrorTreeItem ( watcher . error ) ] )
248
238
}
239
+
240
+ const items :vscode . TreeItem [ ] = [ ]
241
+
242
+ // Add AI tasks first, if the agent has any associated tasks
243
+ const agentTasks = element . agent . tasks . map ( ( task ) => new AITaskTreeItem ( task ) )
244
+ items . push ( ...agentTasks )
245
+
246
+ // Add agent metadata
249
247
const savedMetadata = watcher ?. metadata || [ ]
250
- return Promise . resolve ( savedMetadata . map ( ( metadata ) => new AgentMetadataTreeItem ( metadata ) ) )
248
+ items . push ( ...savedMetadata . map ( ( metadata ) => new AgentMetadataTreeItem ( metadata ) ) )
249
+
250
+ return Promise . resolve ( items )
251
251
}
252
252
253
253
return Promise . resolve ( [ ] )
@@ -320,18 +320,16 @@ class AgentMetadataTreeItem extends vscode.TreeItem {
320
320
321
321
class AITaskTreeItem extends vscode . TreeItem {
322
322
constructor ( public readonly task :WorkspaceAgentTask ) {
323
- super ( task . summary , vscode . TreeItemCollapsibleState . None )
323
+ // Add a hand raise emoji (✋) to indicate tasks awaiting user input
324
+ super ( task . icon , vscode . TreeItemCollapsibleState . None )
324
325
this . description = task . summary
325
326
this . contextValue = "coderAITask"
326
-
327
- // Add an icon using VSCode's built-in Codicons
328
- this . iconPath = new vscode . ThemeIcon ( "sparkle" )
329
-
327
+
330
328
// Add command to handle clicking on the task
331
329
this . command = {
332
- command :"coder.openAITask" ,
330
+ command :"coder.openAITask" ,
333
331
title :"Open AI Task" ,
334
- arguments :[ task ]
332
+ arguments :[ task ] ,
335
333
}
336
334
}
337
335
}
@@ -382,12 +380,16 @@ class AgentTreeItem extends OpenableTreeItem {
382
380
agent . expanded_directory ,
383
381
"coderAgent" ,
384
382
)
383
+
384
+ if ( agent . task_waiting_for_user_input ) {
385
+ this . label = "🙋 " + this . label ;
386
+ }
385
387
}
386
388
}
387
389
388
390
export class WorkspaceTreeItem extends OpenableTreeItem {
389
- public aiTasks :WorkspaceAgentTask [ ] = [ ]
390
-
391
+ public aiTasks :{ waiting : boolean , tasks : WorkspaceAgentTask [ ] } [ ] = [ ]
392
+
391
393
constructor (
392
394
public readonly workspace :Workspace ,
393
395
public readonly showOwner :boolean ,