@@ -105,6 +105,7 @@ type AccountRecord struct {
105105
106106type CreateCodexAPIKeyInput struct {
107107 APIKey string `json:"apiKey"`
108+ Label string `json:"label,omitempty"`
108109 BaseURL string `json:"baseUrl"`
109110 Priority int `json:"priority,omitempty"`
110111 Prefix string `json:"prefix,omitempty"`
@@ -118,11 +119,88 @@ type UpdateCodexAPIKeyPriorityInput struct {
118119 Priority int `json:"priority,omitempty"`
119120}
120121
122+ type UpdateCodexAPIKeyLabelInput struct {
123+ ID string `json:"id"`
124+ Label string `json:"label,omitempty"`
125+ }
126+
127+ type UpdateCodexAPIKeyConfigInput struct {
128+ ID string `json:"id"`
129+ APIKey string `json:"apiKey"`
130+ BaseURL string `json:"baseUrl"`
131+ Prefix string `json:"prefix,omitempty"`
132+ }
133+
121134type UpdateAccountPriorityInput struct {
122135 ID string `json:"id"`
123136 Priority int `json:"priority,omitempty"`
124137}
125138
139+ type OpenAICompatibleProvider struct {
140+ Name string `json:"name"`
141+ Priority int `json:"priority,omitempty"`
142+ Disabled bool `json:"disabled,omitempty"`
143+ BaseURL string `json:"baseUrl"`
144+ Prefix string `json:"prefix,omitempty"`
145+ APIKey string `json:"apiKey"`
146+ APIKeys []string `json:"apiKeys,omitempty"`
147+ Models []OpenAICompatibleModel `json:"models,omitempty"`
148+ Headers map [string ]string `json:"headers,omitempty"`
149+ KeyCount int `json:"keyCount,omitempty"`
150+ ModelCount int `json:"modelCount,omitempty"`
151+ HasHeaders bool `json:"hasHeaders,omitempty"`
152+ }
153+
154+ type OpenAICompatibleModel struct {
155+ Name string `json:"name"`
156+ Alias string `json:"alias,omitempty"`
157+ }
158+
159+ type CreateOpenAICompatibleProviderInput struct {
160+ Name string `json:"name"`
161+ BaseURL string `json:"baseUrl"`
162+ Prefix string `json:"prefix,omitempty"`
163+ APIKey string `json:"apiKey"`
164+ }
165+
166+ type UpdateOpenAICompatibleProviderInput struct {
167+ CurrentName string `json:"currentName"`
168+ Name string `json:"name"`
169+ BaseURL string `json:"baseUrl"`
170+ Prefix string `json:"prefix,omitempty"`
171+ APIKey string `json:"apiKey"`
172+ APIKeys []string `json:"apiKeys,omitempty"`
173+ Headers map [string ]string `json:"headers,omitempty"`
174+ Models []OpenAICompatibleModel `json:"models,omitempty"`
175+ }
176+
177+ type VerifyOpenAICompatibleProviderInput struct {
178+ BaseURL string `json:"baseUrl"`
179+ APIKey string `json:"apiKey"`
180+ Model string `json:"model"`
181+ Headers map [string ]string `json:"headers,omitempty"`
182+ }
183+
184+ type FetchOpenAICompatibleProviderModelsInput struct {
185+ BaseURL string `json:"baseUrl"`
186+ APIKey string `json:"apiKey"`
187+ Headers map [string ]string `json:"headers,omitempty"`
188+ }
189+
190+ type VerifyOpenAICompatibleProviderResult struct {
191+ Success bool `json:"success"`
192+ StatusCode int `json:"statusCode,omitempty"`
193+ Message string `json:"message,omitempty"`
194+ ResponseBody string `json:"responseBody,omitempty"`
195+ }
196+
197+ type FetchOpenAICompatibleProviderModelsResult struct {
198+ Models []OpenAICompatibleModel `json:"models,omitempty"`
199+ StatusCode int `json:"statusCode,omitempty"`
200+ Message string `json:"message,omitempty"`
201+ ResponseBody string `json:"responseBody,omitempty"`
202+ }
203+
126204type RelayServiceConfig struct {
127205 APIKeys []string `json:"apiKeys"`
128206 Endpoints []RelayServiceEndpoint `json:"endpoints"`
@@ -158,6 +236,28 @@ type UsageStatisticsResponse struct {
158236 FailedRequests int64 `json:"failedRequests,omitempty"`
159237}
160238
239+ type LocalProjectedUsageDetail struct {
240+ Timestamp string `json:"timestamp"`
241+ Provider string `json:"provider"`
242+ SourceKind string `json:"sourceKind"`
243+ Model string `json:"model,omitempty"`
244+ InputTokens int64 `json:"inputTokens"`
245+ CachedInputTokens int64 `json:"cachedInputTokens"`
246+ OutputTokens int64 `json:"outputTokens"`
247+ RequestCount int64 `json:"requestCount"`
248+ }
249+
250+ type LocalProjectedUsageResponse struct {
251+ Provider string `json:"provider"`
252+ SourceKind string `json:"sourceKind"`
253+ ScannedFiles int `json:"scannedFiles"`
254+ CacheHitFiles int `json:"cacheHitFiles,omitempty"`
255+ DeltaAppendFiles int `json:"deltaAppendFiles,omitempty"`
256+ FullRebuildFiles int `json:"fullRebuildFiles,omitempty"`
257+ FileMissingFiles int `json:"fileMissingFiles,omitempty"`
258+ Details []LocalProjectedUsageDetail `json:"details"`
259+ }
260+
161261func NewApp () * App {
162262 return & App {
163263 core : wailsapp .New (Version , ReleaseLabel , GitHubRepo ),
@@ -236,6 +336,10 @@ func (a *App) SetAuthFileStatus(name string, disabled bool) error {
236336 return a .core .SetAuthFileStatus (name , disabled )
237337}
238338
339+ func (a * App ) SetAccountDisabled (id string , disabled bool ) error {
340+ return a .core .SetAccountDisabled (id , disabled )
341+ }
342+
239343func (a * App ) DeleteAuthFiles (names []string ) error {
240344 return a .core .DeleteAuthFiles (names )
241345}
@@ -289,6 +393,22 @@ func (a *App) GetUsageStatistics() (*UsageStatisticsResponse, error) {
289393 }, nil
290394}
291395
396+ func (a * App ) GetCodexLocalUsage () (* LocalProjectedUsageResponse , error ) {
397+ result , err := a .core .GetCodexLocalUsage ()
398+ if err != nil {
399+ return nil , err
400+ }
401+ return mapLocalProjectedUsageResponse (result ), nil
402+ }
403+
404+ func (a * App ) RebuildCodexLocalUsage () (* LocalProjectedUsageResponse , error ) {
405+ result , err := a .core .RebuildCodexLocalUsage ()
406+ if err != nil {
407+ return nil , err
408+ }
409+ return mapLocalProjectedUsageResponse (result ), nil
410+ }
411+
292412func (a * App ) StartCodexOAuth () (* OAuthStartResult , error ) {
293413 result , err := a .core .StartCodexOAuth ()
294414 if err != nil {
@@ -354,6 +474,32 @@ func (a *App) ListAccounts() ([]AccountRecord, error) {
354474 return records , nil
355475}
356476
477+ func (a * App ) ListOpenAICompatibleProviders () ([]OpenAICompatibleProvider , error ) {
478+ result , err := a .core .ListOpenAICompatibleProviders ()
479+ if err != nil {
480+ return nil , err
481+ }
482+
483+ providers := make ([]OpenAICompatibleProvider , 0 , len (result ))
484+ for _ , item := range result {
485+ providers = append (providers , OpenAICompatibleProvider {
486+ Name : item .Name ,
487+ Priority : item .Priority ,
488+ Disabled : item .Disabled ,
489+ BaseURL : item .BaseURL ,
490+ Prefix : item .Prefix ,
491+ APIKey : item .APIKey ,
492+ APIKeys : append ([]string (nil ), item .APIKeys ... ),
493+ Models : mapOpenAICompatibleModels (item .Models ),
494+ Headers : item .Headers ,
495+ KeyCount : item .KeyCount ,
496+ ModelCount : item .ModelCount ,
497+ HasHeaders : item .HasHeaders ,
498+ })
499+ }
500+ return providers , nil
501+ }
502+
357503func (a * App ) GetRelayServiceConfig () (* RelayServiceConfig , error ) {
358504 result , err := a .core .GetRelayServiceConfig ()
359505 if err != nil {
@@ -444,6 +590,7 @@ func (a *App) ApplyRelayServiceConfigToLocal(apiKey string, baseURL string) (*Re
444590func (a * App ) CreateCodexAPIKey (input CreateCodexAPIKeyInput ) error {
445591 return a .core .CreateCodexAPIKey (wailsapp.CreateCodexAPIKeyInput {
446592 APIKey : input .APIKey ,
593+ Label : input .Label ,
447594 BaseURL : input .BaseURL ,
448595 Priority : input .Priority ,
449596 Prefix : input .Prefix ,
@@ -453,6 +600,83 @@ func (a *App) CreateCodexAPIKey(input CreateCodexAPIKeyInput) error {
453600 })
454601}
455602
603+ func (a * App ) UpdateCodexAPIKeyLabel (input UpdateCodexAPIKeyLabelInput ) error {
604+ return a .core .UpdateCodexAPIKeyLabel (wailsapp.UpdateCodexAPIKeyLabelInput {
605+ ID : input .ID ,
606+ Label : input .Label ,
607+ })
608+ }
609+
610+ func (a * App ) UpdateCodexAPIKeyConfig (input UpdateCodexAPIKeyConfigInput ) error {
611+ return a .core .UpdateCodexAPIKeyConfig (wailsapp.UpdateCodexAPIKeyConfigInput {
612+ ID : input .ID ,
613+ APIKey : input .APIKey ,
614+ BaseURL : input .BaseURL ,
615+ Prefix : input .Prefix ,
616+ })
617+ }
618+
619+ func (a * App ) CreateOpenAICompatibleProvider (input CreateOpenAICompatibleProviderInput ) error {
620+ return a .core .CreateOpenAICompatibleProvider (wailsapp.CreateOpenAICompatibleProviderInput {
621+ Name : input .Name ,
622+ BaseURL : input .BaseURL ,
623+ Prefix : input .Prefix ,
624+ APIKey : input .APIKey ,
625+ })
626+ }
627+
628+ func (a * App ) DeleteOpenAICompatibleProvider (name string ) error {
629+ return a .core .DeleteOpenAICompatibleProvider (name )
630+ }
631+
632+ func (a * App ) UpdateOpenAICompatibleProvider (input UpdateOpenAICompatibleProviderInput ) error {
633+ return a .core .UpdateOpenAICompatibleProvider (wailsapp.UpdateOpenAICompatibleProviderInput {
634+ CurrentName : input .CurrentName ,
635+ Name : input .Name ,
636+ BaseURL : input .BaseURL ,
637+ Prefix : input .Prefix ,
638+ APIKey : input .APIKey ,
639+ APIKeys : append ([]string (nil ), input .APIKeys ... ),
640+ Headers : input .Headers ,
641+ Models : mapOpenAICompatibleModelsToWails (input .Models ),
642+ })
643+ }
644+
645+ func (a * App ) VerifyOpenAICompatibleProvider (input VerifyOpenAICompatibleProviderInput ) (* VerifyOpenAICompatibleProviderResult , error ) {
646+ result , err := a .core .VerifyOpenAICompatibleProvider (wailsapp.VerifyOpenAICompatibleProviderInput {
647+ BaseURL : input .BaseURL ,
648+ APIKey : input .APIKey ,
649+ Model : input .Model ,
650+ Headers : input .Headers ,
651+ })
652+ if err != nil {
653+ return nil , err
654+ }
655+ return & VerifyOpenAICompatibleProviderResult {
656+ Success : result .Success ,
657+ StatusCode : result .StatusCode ,
658+ Message : result .Message ,
659+ ResponseBody : result .ResponseBody ,
660+ }, nil
661+ }
662+
663+ func (a * App ) FetchOpenAICompatibleProviderModels (input FetchOpenAICompatibleProviderModelsInput ) (* FetchOpenAICompatibleProviderModelsResult , error ) {
664+ result , err := a .core .FetchOpenAICompatibleProviderModels (wailsapp.FetchOpenAICompatibleProviderModelsInput {
665+ BaseURL : input .BaseURL ,
666+ APIKey : input .APIKey ,
667+ Headers : input .Headers ,
668+ })
669+ if err != nil {
670+ return nil , err
671+ }
672+ return & FetchOpenAICompatibleProviderModelsResult {
673+ Models : mapOpenAICompatibleModels (result .Models ),
674+ StatusCode : result .StatusCode ,
675+ Message : result .Message ,
676+ ResponseBody : result .ResponseBody ,
677+ }, nil
678+ }
679+
456680func (a * App ) DeleteCodexAPIKey (id string ) error {
457681 return a .core .DeleteCodexAPIKey (id )
458682}
@@ -480,6 +704,59 @@ func mapAccountRecord(record accountsdomain.AccountRecord) AccountRecord {
480704 }
481705}
482706
707+ func mapLocalProjectedUsageResponse (result * wailsapp.LocalProjectedUsageResponse ) * LocalProjectedUsageResponse {
708+ if result == nil {
709+ return & LocalProjectedUsageResponse {}
710+ }
711+
712+ details := make ([]LocalProjectedUsageDetail , 0 , len (result .Details ))
713+ for _ , detail := range result .Details {
714+ details = append (details , LocalProjectedUsageDetail {
715+ Timestamp : detail .Timestamp ,
716+ Provider : detail .Provider ,
717+ SourceKind : detail .SourceKind ,
718+ Model : detail .Model ,
719+ InputTokens : detail .InputTokens ,
720+ CachedInputTokens : detail .CachedInputTokens ,
721+ OutputTokens : detail .OutputTokens ,
722+ RequestCount : detail .RequestCount ,
723+ })
724+ }
725+
726+ return & LocalProjectedUsageResponse {
727+ Provider : result .Provider ,
728+ SourceKind : result .SourceKind ,
729+ ScannedFiles : result .ScannedFiles ,
730+ CacheHitFiles : result .CacheHitFiles ,
731+ DeltaAppendFiles : result .DeltaAppendFiles ,
732+ FullRebuildFiles : result .FullRebuildFiles ,
733+ FileMissingFiles : result .FileMissingFiles ,
734+ Details : details ,
735+ }
736+ }
737+
738+ func mapOpenAICompatibleModels (items []wailsapp.OpenAICompatibleModel ) []OpenAICompatibleModel {
739+ models := make ([]OpenAICompatibleModel , 0 , len (items ))
740+ for _ , item := range items {
741+ models = append (models , OpenAICompatibleModel {
742+ Name : item .Name ,
743+ Alias : item .Alias ,
744+ })
745+ }
746+ return models
747+ }
748+
749+ func mapOpenAICompatibleModelsToWails (items []OpenAICompatibleModel ) []wailsapp.OpenAICompatibleModel {
750+ models := make ([]wailsapp.OpenAICompatibleModel , 0 , len (items ))
751+ for _ , item := range items {
752+ models = append (models , wailsapp.OpenAICompatibleModel {
753+ Name : item .Name ,
754+ Alias : item .Alias ,
755+ })
756+ }
757+ return models
758+ }
759+
483760func mapRelayServiceEndpoints (items []wailsapp.RelayServiceEndpoint ) []RelayServiceEndpoint {
484761 endpoints := make ([]RelayServiceEndpoint , 0 , len (items ))
485762 for _ , item := range items {
0 commit comments