mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 03:29:25 +01:00
124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import { inject } from '@adonisjs/core'
|
|
import { chromium } from 'playwright'
|
|
import { SystemService } from './system_service.js'
|
|
import logger from '@adonisjs/core/services/logger'
|
|
import { DockerService } from './docker_service.js'
|
|
import { ServiceSlim } from '../../types/services.js'
|
|
import axios from 'axios'
|
|
|
|
@inject()
|
|
export class OpenWebUIService {
|
|
constructor(private systemService: SystemService) {}
|
|
|
|
async getOpenWebUIToken(): Promise<{
|
|
token: string
|
|
location: string
|
|
} | null> {
|
|
try {
|
|
const { openWebUIService } = await this.getOpenWebUIAndOllamaServices()
|
|
if (!openWebUIService) {
|
|
logger.warn('[OpenWebUIService] Open WebUI service is not installed.')
|
|
return null
|
|
}
|
|
|
|
const location = this.extractOpenWebUIUrl(openWebUIService)
|
|
if (!location) {
|
|
logger.warn('[OpenWebUIService] Could not determine Open WebUI URL.')
|
|
return null
|
|
}
|
|
|
|
const browser = await chromium.launch({ headless: true })
|
|
const context = await browser.newContext()
|
|
const page = await context.newPage()
|
|
|
|
try {
|
|
await page.goto(location, { waitUntil: 'networkidle' })
|
|
|
|
const cookies = await context.cookies()
|
|
const tokenCookie = cookies.find((cookie) => cookie.name === 'token')
|
|
if (tokenCookie) {
|
|
return { token: tokenCookie.value, location }
|
|
}
|
|
|
|
return null
|
|
} finally {
|
|
await browser.close()
|
|
}
|
|
} catch (error) {
|
|
logger.error(
|
|
`[OpenWebUIService] Failed to get Open WebUI token: ${error instanceof Error ? error.message : error}`
|
|
)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async getInstalledModels(): Promise<string[] | null> {
|
|
try {
|
|
const tokenData = await this.getOpenWebUIToken()
|
|
if (!tokenData) {
|
|
logger.warn('[OpenWebUIService] Cannot get installed models without Open WebUI token.')
|
|
return null
|
|
}
|
|
|
|
const response = await axios.get(tokenData.location + '/ollama/api/tags', {
|
|
headers: {
|
|
Authorization: `Bearer ${tokenData.token}`,
|
|
},
|
|
})
|
|
|
|
if (response.status === 200 && response.data.models && Array.isArray(response.data.models)) {
|
|
console.log("GOT RESPONSE DATA:", response.data)
|
|
return response.data.models as string[]
|
|
}
|
|
|
|
logger.warn(
|
|
`[OpenWebUIService] Unexpected response when fetching installed models: ${response.status}`
|
|
)
|
|
return null
|
|
} catch (error) {
|
|
logger.error(
|
|
`[OpenWebUIService] Failed to get installed models: ${error instanceof Error ? error.message : error}`
|
|
)
|
|
return null
|
|
}
|
|
}
|
|
|
|
private async getOpenWebUIAndOllamaServices(): Promise<{
|
|
openWebUIService: ServiceSlim | null
|
|
ollamaService: ServiceSlim | null
|
|
}> {
|
|
try {
|
|
const services = await this.systemService.getServices({ installedOnly: true })
|
|
|
|
const owuiContainer = services.find(
|
|
(service) => service.service_name === DockerService.OPEN_WEBUI_SERVICE_NAME
|
|
)
|
|
const ollamaContainer = services.find(
|
|
(service) => service.service_name === DockerService.OLLAMA_SERVICE_NAME
|
|
)
|
|
|
|
return {
|
|
openWebUIService: owuiContainer || null,
|
|
ollamaService: ollamaContainer || null,
|
|
}
|
|
} catch (error) {
|
|
logger.error(
|
|
`[OpenWebUIService] Failed to get Open WebUI and Ollama services: ${error instanceof Error ? error.message : error}`
|
|
)
|
|
return {
|
|
openWebUIService: null,
|
|
ollamaService: null,
|
|
}
|
|
}
|
|
}
|
|
|
|
private extractOpenWebUIUrl(service: ServiceSlim): string | null {
|
|
const location = service.ui_location || '3000'
|
|
if (!location || isNaN(Number(location))) {
|
|
logger.warn(`[OpenWebUIService] Invalid Open WebUI location: ${location}`)
|
|
return null
|
|
}
|
|
return `http://localhost:${location}`
|
|
}
|
|
}
|