|
1 | 1 | import { Api } from "coder/site/src/api/api" |
2 | | -import { Workspace, WorkspaceAgent, WorkspaceAgentTask } from "coder/site/src/api/typesGenerated" |
| 2 | +import { Workspace, WorkspaceAgent } from "coder/site/src/api/typesGenerated" |
3 | 3 | import { EventSource } from "eventsource" |
4 | 4 | import * as path from "path" |
5 | 5 | import * as vscode from "vscode" |
@@ -155,14 +155,26 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte |
155 | 155 | showMetadata, |
156 | 156 | ) |
157 | 157 |
|
158 | | - // Fetch AI tasks for the workspace |
| 158 | + // Get app status from the workspace agents |
159 | 159 | try { |
160 | | - // Create a dummy emitter for logs |
161 | | - const _emitter = new vscode.EventEmitter<string>() |
| 160 | + const agents = extractAgents(workspace) |
| 161 | + agents.forEach((agent) => { |
| 162 | + // Check if agent has apps property with status reporting |
| 163 | + if (agent.apps && Array.isArray(agent.apps)) { |
| 164 | + workspaceTreeItem.appStatus = agent.apps.map((app) => ({ |
| 165 | + name: app.display_name || app.name || "App", |
| 166 | + status: app.status || "Running", |
| 167 | + icon: app.icon || "$(pulse)", |
| 168 | + url: app.url, |
| 169 | + agent_id: agent.id, |
| 170 | + agent_name: agent.name, |
| 171 | + })) |
| 172 | + } |
| 173 | + }) |
162 | 174 | } catch (error) { |
163 | | - // Log the error but continue - we don't want to fail the whole tree if AI tasks fail |
| 175 | + // Log the error but continue - we don't want to fail the whole tree if app status fails |
164 | 176 | this.storage.writeToCoderOutputChannel( |
165 | | - `Failed to fetch AI tasks for workspace ${workspace.name}: ${errToStr(error, "unknown error")}`, |
| 177 | + `Failed to get app status for workspace ${workspace.name}: ${errToStr(error, "unknown error")}`, |
166 | 178 | ) |
167 | 179 | } |
168 | 180 |
|
@@ -239,13 +251,24 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte |
239 | 251 |
|
240 | 252 | const items: vscode.TreeItem[] = [] |
241 | 253 |
|
242 | | - // Add AI tasks section with collapsible header |
243 | | - if (element.agent.tasks.length > 0) { |
244 | | - const aiTasksSection = new SectionTreeItem( |
245 | | - "AI Tasks", |
246 | | - element.agent.tasks.map((task) => new AITaskTreeItem(task)), |
| 254 | + // Add app status section with collapsible header |
| 255 | + if (element.agent.apps && element.agent.apps.length > 0) { |
| 256 | + let needsAttention = [] |
| 257 | + for (const app of element.agent.apps) { |
| 258 | + if (app.statuses && app.statuses.length > 0) { |
| 259 | + for (const status of app.statuses) { |
| 260 | + if (status.needs_user_attention) { |
| 261 | + needsAttention.push(new AppStatusTreeItem(status)) |
| 262 | + } |
| 263 | + } |
| 264 | + } |
| 265 | + } |
| 266 | + |
| 267 | + const appStatusSection = new SectionTreeItem( |
| 268 | + "Applications in need of attention", |
| 269 | + needsAttention, |
247 | 270 | ) |
248 | | - items.push(aiTasksSection) |
| 271 | + items.push(appStatusSection) |
249 | 272 | } |
250 | 273 |
|
251 | 274 | const savedMetadata = watcher?.metadata || [] |
@@ -346,18 +369,27 @@ class AgentMetadataTreeItem extends vscode.TreeItem { |
346 | 369 | } |
347 | 370 | } |
348 | 371 |
|
349 | | -class AITaskTreeItem extends vscode.TreeItem { |
350 | | - constructor(public readonly task: WorkspaceAgentTask) { |
351 | | - // Add a hand raise emoji (✋) to indicate tasks awaiting user input |
352 | | - super(task.icon, vscode.TreeItemCollapsibleState.None) |
353 | | - this.description = task.summary |
354 | | - this.contextValue = "coderAITask" |
| 372 | +class AppStatusTreeItem extends vscode.TreeItem { |
| 373 | + constructor( |
| 374 | + public readonly app: { |
| 375 | + name?: string |
| 376 | + display_name?: string |
| 377 | + status?: string |
| 378 | + icon?: string |
| 379 | + url?: string |
| 380 | + agent_id?: string |
| 381 | + agent_name?: string |
| 382 | + }, |
| 383 | + ) { |
| 384 | + super(app.icon || "$(pulse)", vscode.TreeItemCollapsibleState.None) |
| 385 | + this.description = app.status || "Running" |
| 386 | + this.contextValue = "coderAppStatus" |
355 | 387 |
|
356 | | - // Add command to handle clicking on the task |
| 388 | + // Add command to handle clicking on the app |
357 | 389 | this.command = { |
358 | | - command: "coder.openAITask", |
359 | | - title: "Open AI Task", |
360 | | - arguments: [task], |
| 390 | + command: "coder.openAppStatus", |
| 391 | + title: "Open App Status", |
| 392 | + arguments: [app], |
361 | 393 | } |
362 | 394 | } |
363 | 395 | } |
@@ -409,14 +441,15 @@ class AgentTreeItem extends OpenableTreeItem { |
409 | 441 | "coderAgent", |
410 | 442 | ) |
411 | 443 |
|
412 | | - if (agent.task_waiting_for_user_input) { |
413 | | - this.label = "🙋 " + this.label |
| 444 | + if (agent.apps && agent.apps.length > 0) { |
| 445 | + // Add an icon to indicate this agent has running apps |
| 446 | + this.label = "🖐️ " + this.label |
414 | 447 | } |
415 | 448 | } |
416 | 449 | } |
417 | 450 |
|
418 | 451 | export class WorkspaceTreeItem extends OpenableTreeItem { |
419 | | - public aiTasks: { waiting: boolean; tasks: WorkspaceAgentTask[] }[] = [] |
| 452 | + public appStatus: { name: string; status: string; icon?: string }[] = [] |
420 | 453 |
|
421 | 454 | constructor( |
422 | 455 | public readonly workspace: Workspace, |
|
0 commit comments