Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 90 additions & 38 deletions web/default/src/features/channels/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.

For commercial licensing, please contact support@quantumnous.com
*/
import type { AxiosRequestConfig } from 'axios'
import { api } from '@/lib/api'
import { api, type ApiRequestConfig } from '@/lib/api'
import { getGroups as getUserGroups } from '@/features/users/api'
import type {
AddChannelRequest,
Expand All @@ -39,11 +38,13 @@ import type {
TagOperationParams,
} from './types'

// Extended API config types
interface ExtendedApiConfig extends AxiosRequestConfig {
skipBusinessError?: boolean
disableDuplicate?: boolean
}
const channelActionConfig = (
config: ApiRequestConfig = {}
): ApiRequestConfig => ({
...config,
skipBusinessError: true,
skipErrorHandler: true,
})

export type CodexOAuthStartResponse = {
success: boolean
Expand Down Expand Up @@ -125,7 +126,7 @@ export async function getChannel(id: number): Promise<GetChannelResponse> {
export async function createChannel(
data: AddChannelRequest
): Promise<{ success: boolean; message?: string }> {
const res = await api.post('/api/channel', data)
const res = await api.post('/api/channel', data, channelActionConfig())
return res.data
}

Expand All @@ -136,7 +137,11 @@ export async function updateChannel(
id: number,
data: Partial<Channel>
): Promise<{ success: boolean; message?: string; data?: Channel }> {
const res = await api.put('/api/channel/', { id, ...data })
const res = await api.put(
'/api/channel/',
{ id, ...data },
channelActionConfig()
)
return res.data
}

Expand All @@ -146,7 +151,7 @@ export async function updateChannel(
export async function deleteChannel(
id: number
): Promise<{ success: boolean; message?: string }> {
const res = await api.delete(`/api/channel/${id}`)
const res = await api.delete(`/api/channel/${id}`, channelActionConfig())
return res.data
}

Expand All @@ -156,7 +161,7 @@ export async function deleteChannel(
export async function batchDeleteChannels(
data: BatchDeleteParams
): Promise<{ success: boolean; message?: string; data?: number }> {
const res = await api.post('/api/channel/batch', data)
const res = await api.post('/api/channel/batch', data, channelActionConfig())
return res.data
}

Expand All @@ -166,7 +171,11 @@ export async function batchDeleteChannels(
export async function batchSetChannelTag(
data: BatchSetTagParams
): Promise<{ success: boolean; message?: string; data?: number }> {
const res = await api.post('/api/channel/batch/tag', data)
const res = await api.post(
'/api/channel/batch/tag',
data,
channelActionConfig()
)
return res.data
}

Expand All @@ -181,7 +190,10 @@ export async function testChannel(
id: number,
params?: { model?: string; endpoint_type?: string; stream?: boolean }
): Promise<ChannelTestResponse> {
const res = await api.get(`/api/channel/test/${id}`, { params })
const res = await api.get(
`/api/channel/test/${id}`,
channelActionConfig({ params })
)
return res.data
}

Expand All @@ -191,7 +203,10 @@ export async function testChannel(
export async function updateChannelBalance(
id: number
): Promise<ChannelBalanceResponse> {
const res = await api.get(`/api/channel/update_balance/${id}`)
const res = await api.get(
`/api/channel/update_balance/${id}`,
channelActionConfig()
)
return res.data
}

Expand All @@ -201,7 +216,10 @@ export async function updateChannelBalance(
export async function fetchUpstreamModels(
id: number
): Promise<FetchModelsResponse> {
const res = await api.get(`/api/channel/fetch_models/${id}`)
const res = await api.get(
`/api/channel/fetch_models/${id}`,
channelActionConfig()
)
return res.data
}

Expand All @@ -212,7 +230,11 @@ export async function copyChannel(
id: number,
params: CopyChannelParams = {}
): Promise<CopyChannelResponse> {
const res = await api.post(`/api/channel/copy/${id}`, null, { params })
const res = await api.post(
`/api/channel/copy/${id}`,
null,
channelActionConfig({ params })
)
return res.data
}

Expand All @@ -224,7 +246,11 @@ export async function fixChannelAbilities(): Promise<{
message?: string
data?: { success: number; fails: number }
}> {
const res = await api.post('/api/channel/fix')
const res = await api.post(
'/api/channel/fix',
undefined,
channelActionConfig()
)
return res.data
}

Expand All @@ -236,7 +262,7 @@ export async function deleteDisabledChannels(): Promise<{
message?: string
data?: number
}> {
const res = await api.delete('/api/channel/disabled')
const res = await api.delete('/api/channel/disabled', channelActionConfig())
return res.data
}

Expand All @@ -248,7 +274,11 @@ export async function getChannelKey(
code?: string
): Promise<{ success: boolean; message?: string; data?: { key: string } }> {
const payload = code ? { code } : undefined
const res = await api.post(`/api/channel/${id}/key`, payload)
const res = await api.post(
`/api/channel/${id}/key`,
payload,
channelActionConfig()
)
return res.data
}

Expand All @@ -257,43 +287,43 @@ export async function getChannelKey(
// ============================================================================

export async function startCodexOAuth(): Promise<CodexOAuthStartResponse> {
const config: ExtendedApiConfig = { skipBusinessError: true }
const res = await api.post('/api/channel/codex/oauth/start', {}, config)
const res = await api.post(
'/api/channel/codex/oauth/start',
{},
channelActionConfig()
)
return res.data
}

export async function completeCodexOAuth(
input: string
): Promise<CodexOAuthCompleteResponse> {
const config: ExtendedApiConfig = { skipBusinessError: true }
const res = await api.post(
'/api/channel/codex/oauth/complete',
{ input },
config
channelActionConfig()
)
return res.data
}

export async function refreshCodexCredential(
channelId: number
): Promise<CodexCredentialRefreshResponse> {
const config: ExtendedApiConfig = { skipBusinessError: true }
const res = await api.post(
`/api/channel/${channelId}/codex/refresh`,
{},
config
channelActionConfig()
)
return res.data
}

export async function getCodexUsage(
channelId: number
): Promise<CodexUsageResponse> {
const config: ExtendedApiConfig = {
skipBusinessError: true,
disableDuplicate: true,
}
const res = await api.get(`/api/channel/${channelId}/codex/usage`, config)
const res = await api.get(
`/api/channel/${channelId}/codex/usage`,
channelActionConfig({ disableDuplicate: true })
)
return res.data
}

Expand All @@ -307,7 +337,11 @@ export async function getCodexUsage(
export async function manageMultiKeys(
params: MultiKeyManageParams
): Promise<MultiKeyStatusResponse | { success: boolean; message?: string }> {
const res = await api.post('/api/channel/multi_key/manage', params)
const res = await api.post(
'/api/channel/multi_key/manage',
params,
channelActionConfig()
)
return res.data
}

Expand Down Expand Up @@ -417,7 +451,11 @@ export async function deleteDisabledMultiKeys(
export async function enableTagChannels(
tag: string
): Promise<{ success: boolean; message?: string }> {
const res = await api.post('/api/channel/tag/enabled', { tag })
const res = await api.post(
'/api/channel/tag/enabled',
{ tag },
channelActionConfig()
)
return res.data
}

Expand All @@ -427,7 +465,11 @@ export async function enableTagChannels(
export async function disableTagChannels(
tag: string
): Promise<{ success: boolean; message?: string }> {
const res = await api.post('/api/channel/tag/disabled', { tag })
const res = await api.post(
'/api/channel/tag/disabled',
{ tag },
channelActionConfig()
)
return res.data
}

Expand All @@ -437,7 +479,7 @@ export async function disableTagChannels(
export async function editTagChannels(
params: TagOperationParams
): Promise<{ success: boolean; message?: string }> {
const res = await api.put('/api/channel/tag', params)
const res = await api.put('/api/channel/tag', params, channelActionConfig())
return res.data
}

Expand All @@ -463,7 +505,11 @@ export async function fetchModels(data: {
type: number
key: string
}): Promise<FetchModelsResponse> {
const res = await api.post('/api/channel/fetch_models', data)
const res = await api.post(
'/api/channel/fetch_models',
data,
channelActionConfig()
)
return res.data
}

Expand All @@ -474,7 +520,10 @@ export async function deleteOllamaModel(params: {
channel_id: number
model_name: string
}): Promise<{ success: boolean; message?: string }> {
const res = await api.delete('/api/channel/ollama/delete', { data: params })
const res = await api.delete(
'/api/channel/ollama/delete',
channelActionConfig({ data: params })
)
return res.data
}

Expand All @@ -485,7 +534,7 @@ export async function testAllChannels(): Promise<{
success: boolean
message?: string
}> {
const res = await api.get('/api/channel/test')
const res = await api.get('/api/channel/test', channelActionConfig())
return res.data
}

Expand All @@ -496,7 +545,10 @@ export async function updateAllChannelsBalance(): Promise<{
success: boolean
message?: string
}> {
const res = await api.get('/api/channel/update_balance')
const res = await api.get(
'/api/channel/update_balance',
channelActionConfig()
)
return res.data
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export function MultiKeyManageDialog({
setEnabledCount(response.data.enabled_count || 0)
setManualDisabledCount(response.data.manual_disabled_count || 0)
setAutoDisabledCount(response.data.auto_disabled_count || 0)
} else {
toast.error(response.message || t('Failed to load key status'))
}
} catch (error: unknown) {
toast.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,22 @@ export function OllamaModelsDialog({
? Array.from(new Set(selected))
: Array.from(new Set([...existingModels, ...selected]))

const res = await updateChannel(currentRow.id, { models: next.join(',') })
if (res.success) {
toast.success(
mode === 'replace'
? t('Models updated successfully')
: t('Models appended successfully')
try {
const res = await updateChannel(currentRow.id, { models: next.join(',') })
if (res.success) {
toast.success(
mode === 'replace'
? t('Models updated successfully')
: t('Models appended successfully')
)
queryClient.invalidateQueries({ queryKey: channelsQueryKeys.lists() })
} else {
toast.error(res.message || t('Failed to update models'))
}
} catch (err: unknown) {
toast.error(
err instanceof Error ? err.message : t('Failed to update models')
)
queryClient.invalidateQueries({ queryKey: channelsQueryKeys.lists() })
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,8 @@ export function ChannelMutateDrawer({
if (response.success) {
toast.success(t(SUCCESS_MESSAGES.UPDATED))
handleSuccess()
} else {
throw new Error(response.message || t(ERROR_MESSAGES.UPDATE_FAILED))
}
} else {
// Create new channel(s)
Expand All @@ -1041,6 +1043,8 @@ export function ChannelMutateDrawer({
if (response.success) {
toast.success(t(SUCCESS_MESSAGES.CREATED))
handleSuccess()
} else {
throw new Error(response.message || t(ERROR_MESSAGES.CREATE_FAILED))
}
}
} catch (error: unknown) {
Expand Down Expand Up @@ -3381,7 +3385,9 @@ export function ChannelMutateDrawer({
redirectSourceModels={redirectModelKeyList}
customFetcher={!isEditing ? createModeFetcher : undefined}
existingModelsOverride={
!isEditing ? parseModelsString(form.getValues('models') || '') : undefined
!isEditing
? parseModelsString(form.getValues('models') || '')
: undefined
}
/>

Expand Down
Loading