@@ -22,9 +22,10 @@ import (
2222func newListCmd () * cobra.Command {
2323 var jsonFormat , openai , quiet bool
2424 c := & cobra.Command {
25- Use : "list [OPTIONS]" ,
25+ Use : "list [OPTIONS] [MODEL] " ,
2626 Aliases : []string {"ls" },
2727 Short : "List the models pulled to your local environment" ,
28+ Args : cobra .MaximumNArgs (1 ),
2829 RunE : func (cmd * cobra.Command , args []string ) error {
2930 if openai && quiet {
3031 return fmt .Errorf ("--quiet flag cannot be used with --openai flag or OpenAI backend" )
@@ -58,58 +59,63 @@ func newListCmd() *cobra.Command {
5859 return c
5960}
6061
62+ func normalizeModelFilter (filter string ) string {
63+ if ! strings .Contains (filter , "/" ) {
64+ return "ai/" + filter
65+ }
66+ return filter
67+ }
68+
69+ func matchesModelFilter (tag , filter string ) bool {
70+ if strings .Contains (filter , ":" ) {
71+ return tag == filter
72+ }
73+ repository , _ , _ := strings .Cut (tag , ":" )
74+ return repository == filter
75+ }
76+
6177func listModels (openai bool , desktopClient * desktop.Client , quiet bool , jsonFormat bool , modelFilter string ) (string , error ) {
6278 if openai {
6379 models , err := desktopClient .ListOpenAI ()
6480 if err != nil {
6581 return "" , handleClientError (err , "Failed to list models" )
6682 }
83+ if modelFilter != "" {
84+ filter := normalizeModelFilter (modelFilter )
85+ filtered := models .Data [:0 ]
86+ for _ , m := range models .Data {
87+ if matchesModelFilter (m .ID , filter ) {
88+ filtered = append (filtered , m )
89+ }
90+ }
91+ models .Data = filtered
92+ }
6793 return formatter .ToStandardJSON (models )
6894 }
95+
6996 models , err := desktopClient .List ()
7097 if err != nil {
7198 return "" , handleClientError (err , "Failed to list models" )
7299 }
73-
74100 if modelFilter != "" {
75- // If filter doesn't contain '/', prepend default namespace 'ai/'
76- if ! strings .Contains (modelFilter , "/" ) {
77- modelFilter = "ai/" + modelFilter
78- }
79-
101+ filter := normalizeModelFilter (modelFilter )
80102 var filteredModels []dmrm.Model
81103
82- // Check if filter has a colon (i.e., includes a tag)
83- hasColon := strings .Contains (modelFilter , ":" )
84-
85104 for _ , m := range models {
86105 var matchingTags []string
87106 for _ , tag := range m .Tags {
88- if hasColon {
89- // Filter includes a tag part - do exact match
90- // Tags are stored in normalized format by the backend
91- if tag == modelFilter {
92- matchingTags = append (matchingTags , tag )
93- }
94- } else {
95- // Filter has no colon - match repository name only (part before ':')
96- repository , _ , _ := strings .Cut (tag , ":" )
97- if repository == modelFilter {
98- matchingTags = append (matchingTags , tag )
99- }
107+ if matchesModelFilter (tag , filter ) {
108+ matchingTags = append (matchingTags , tag )
100109 }
101110 }
102- // Only include the model if at least one tag matched, and only include matching tags
103111 if len (matchingTags ) > 0 {
104- // Create a copy of the model with only the matching tags
105112 filteredModel := m
106113 filteredModel .Tags = matchingTags
107114 filteredModels = append (filteredModels , filteredModel )
108115 }
109116 }
110117 models = filteredModels
111118 }
112-
113119 if jsonFormat {
114120 return formatter .ToStandardJSON (models )
115121 }
0 commit comments