({ workspace })
| 651 | }; |
| 652 | |
| 653 | const WorkspaceApps: FC<WorkspaceAppsProps> = ({ workspace }) => { |
| 654 | /** |
| 655 | * Coder is pretty flexible and allows an enormous variety of use cases, such |
| 656 | * as having multiple resources with many agents, but they are not common. The |
| 657 | * most common scenario is to have one single compute resource with one single |
| 658 | * agent containing all the apps. We get the apps from the first compute |
| 659 | * resource (they are sorted to return the compute resource first). |
| 660 | * |
| 661 | * For multi-agent workspaces with sub-agents we show the apps from the parent |
| 662 | * agent (the one without a `parent_id`). Sub-agents, such as those created by |
| 663 | * devcontainers, are skipped so agent ordering does not determine which apps |
| 664 | * appear. |
| 665 | * |
| 666 | * When a workspace has multiple parent-level agents we show the apps from the |
| 667 | * first one only; aggregating apps across agents is tracked separately. |
| 668 | */ |
| 669 | const agent = workspace.latest_build.resources |
| 670 | .filter((r) => !r.hide) |
| 671 | .at(0) |
| 672 | ?.agents?.find((a) => a.parent_id === null); |
| 673 | if (!agent) { |
| 674 | return null; |
| 675 | } |
| 676 | |
| 677 | const builtinApps = new Set(agent.display_apps); |
| 678 | builtinApps.delete("port_forwarding_helper"); |
| 679 | builtinApps.delete("ssh_helper"); |
| 680 | |
| 681 | const remainingSlots = WORKSPACE_APPS_SLOTS - builtinApps.size; |
| 682 | const userApps = agent.apps |
| 683 | .filter( |
| 684 | (app) => |
| 685 | (app.health === "healthy" || app.health === "disabled") && !app.hidden, |
| 686 | ) |
| 687 | .slice(0, remainingSlots); |
| 688 | |
| 689 | const buttons: ReactNode[] = []; |
| 690 | |
| 691 | if (builtinApps.has("vscode")) { |
| 692 | buttons.push( |
| 693 | <VSCodeIconLink |
| 694 | key="vscode" |
| 695 | variant="vscode" |
| 696 | label="Open VSCode" |
| 697 | owner={workspace.owner_name} |
| 698 | workspace={workspace.name} |
| 699 | agent={agent.name} |
| 700 | folder={agent.expanded_directory} |
| 701 | > |
| 702 | <VSCodeIcon /> |
| 703 | </VSCodeIconLink>, |
| 704 | ); |
| 705 | } |
| 706 | |
| 707 | if (builtinApps.has("vscode_insiders")) { |
| 708 | buttons.push( |
| 709 | <VSCodeIconLink |
| 710 | key="vscode-insiders" |
nothing calls this directly
no test coverage detected