mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(cli): add dynamic completions for ssh command (#20171)
Adds CompletionHandler to the ssh command that dynamically suggests workspace and agent targets based on the user's running workspaces. Features: - Suggests workspace name for single-agent workspaces - Suggests agent.workspace format for all agents in multi-agent workspaces - Only shows running workspaces (matches immediate availability) - Alphabetically sorted completions for better UX Tests cover single-agent, multi-agent, and network error scenarios. Amp-Thread-ID: https://ampcode.com/threads/T-d137d343-53f3-4ece-be5a-584249bbd9e8 <!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> closes #20158 Demo: https://github.com/user-attachments/assets/e1000463-ded6-4bc9-b013-61780453f019 --------- Co-authored-by: Ethan Dickson <ethan@coder.com>
This commit is contained in:
co-authored by
Ethan Dickson
parent
b89093031e
commit
9780d0295c
+45
@@ -109,6 +109,51 @@ func (r *RootCmd) ssh() *serpent.Command {
|
||||
}
|
||||
},
|
||||
),
|
||||
CompletionHandler: func(inv *serpent.Invocation) []string {
|
||||
client, err := r.InitClient(inv)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
res, err := client.Workspaces(inv.Context(), codersdk.WorkspaceFilter{
|
||||
Owner: codersdk.Me,
|
||||
})
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
var completions []string
|
||||
var wg sync.WaitGroup
|
||||
for _, ws := range res.Workspaces {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
resources, err := client.TemplateVersionResources(inv.Context(), ws.LatestBuild.TemplateVersionID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var agents []codersdk.WorkspaceAgent
|
||||
for _, resource := range resources {
|
||||
agents = append(agents, resource.Agents...)
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if len(agents) == 1 {
|
||||
completions = append(completions, ws.Name)
|
||||
} else {
|
||||
for _, agent := range agents {
|
||||
completions = append(completions, fmt.Sprintf("%s.%s", ws.Name, agent.Name))
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
slices.Sort(completions)
|
||||
return completions
|
||||
},
|
||||
Handler: func(inv *serpent.Invocation) (retErr error) {
|
||||
client, err := r.InitClient(inv)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user