Skip to content

Commit 31c671b

Browse files
committed
fix: service name defs and ollama ui location
1 parent 4584844 commit 31c671b

File tree

15 files changed

+62
-44
lines changed

15 files changed

+62
-44
lines changed

admin/app/services/benchmark_service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
} from '../../types/benchmark.js'
2525
import { randomUUID, createHmac } from 'node:crypto'
2626
import { DockerService } from './docker_service.js'
27+
import { SERVICE_NAMES } from '../../constants/service_names.js'
2728

2829
// HMAC secret for signing submissions to the benchmark repository
2930
// This provides basic protection against casual API abuse.
@@ -421,7 +422,7 @@ export class BenchmarkService {
421422

422423
this._updateStatus('running_ai', 'Running AI benchmark...')
423424

424-
const ollamaAPIURL = await this.dockerService.getServiceURL(DockerService.OLLAMA_SERVICE_NAME)
425+
const ollamaAPIURL = await this.dockerService.getServiceURL(SERVICE_NAMES.OLLAMA)
425426
if (!ollamaAPIURL) {
426427
throw new Error('AI Assistant service location could not be determined. Ensure AI Assistant is installed and running.')
427428
}

admin/app/services/docker_service.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,12 @@ import transmit from '@adonisjs/transmit/services/main'
66
import { doResumableDownloadWithRetry } from '../utils/downloads.js'
77
import { join } from 'path'
88
import { ZIM_STORAGE_PATH } from '../utils/fs.js'
9+
import { SERVICE_NAMES } from '../../constants/service_names.js'
910

1011
@inject()
1112
export class DockerService {
1213
public docker: Docker
1314
private activeInstallations: Set<string> = new Set()
14-
public static KIWIX_SERVICE_NAME = 'nomad_kiwix_serve'
15-
public static OLLAMA_SERVICE_NAME = 'nomad_ollama'
16-
public static QDRANT_SERVICE_NAME = 'nomad_qdrant'
17-
public static CYBERCHEF_SERVICE_NAME = 'nomad_cyberchef'
18-
public static FLATNOTES_SERVICE_NAME = 'nomad_flatnotes'
19-
public static KOLIBRI_SERVICE_NAME = 'nomad_kolibri'
20-
public static BENCHMARK_SERVICE_NAME = 'nomad_benchmark'
2115
public static NOMAD_NETWORK = 'project-nomad_default'
2216

2317
constructor() {
@@ -441,7 +435,7 @@ export class DockerService {
441435
await new Promise((res) => this.docker.modem.followProgress(pullStream, res))
442436
}
443437

444-
if (service.service_name === DockerService.KIWIX_SERVICE_NAME) {
438+
if (service.service_name === SERVICE_NAMES.KIWIX) {
445439
await this._runPreinstallActions__KiwixServe()
446440
this._broadcast(
447441
service.service_name,
@@ -556,12 +550,12 @@ export class DockerService {
556550
logger.info(`[DockerService] Kiwix Serve pre-install: Downloading ZIM file to ${filepath}`)
557551

558552
this._broadcast(
559-
DockerService.KIWIX_SERVICE_NAME,
553+
SERVICE_NAMES.KIWIX,
560554
'preinstall',
561555
`Running pre-install actions for Kiwix Serve...`
562556
)
563557
this._broadcast(
564-
DockerService.KIWIX_SERVICE_NAME,
558+
SERVICE_NAMES.KIWIX,
565559
'preinstall',
566560
`Downloading Wikipedia ZIM file from ${WIKIPEDIA_ZIM_URL}. This may take some time...`
567561
)
@@ -579,13 +573,13 @@ export class DockerService {
579573
})
580574

581575
this._broadcast(
582-
DockerService.KIWIX_SERVICE_NAME,
576+
SERVICE_NAMES.KIWIX,
583577
'preinstall',
584578
`Downloaded Wikipedia ZIM file to ${filepath}`
585579
)
586580
} catch (error) {
587581
this._broadcast(
588-
DockerService.KIWIX_SERVICE_NAME,
582+
SERVICE_NAMES.KIWIX,
589583
'preinstall-error',
590584
`Failed to download Wikipedia ZIM file: ${error.message}`
591585
)

admin/app/services/ollama_service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { inject } from '@adonisjs/core'
22
import { ChatRequest, Ollama } from 'ollama'
3-
import { DockerService } from './docker_service.js'
43
import { NomadOllamaModel } from '../../types/ollama.js'
54
import { FALLBACK_RECOMMENDED_OLLAMA_MODELS } from '../../constants/ollama.js'
65
import fs from 'node:fs/promises'
@@ -9,6 +8,7 @@ import logger from '@adonisjs/core/services/logger'
98
import axios from 'axios'
109
import { DownloadModelJob } from '#jobs/download_model_job'
1110
import { PassThrough } from 'node:stream'
11+
import { SERVICE_NAMES } from '../../constants/service_names.js'
1212

1313
const NOMAD_MODELS_API_BASE_URL = 'https://api.projectnomad.us/api/v1/ollama/models'
1414
const MODELS_CACHE_FILE = path.join(process.cwd(), 'storage', 'ollama-models-cache.json')
@@ -25,7 +25,7 @@ export class OllamaService {
2525
if (!this.ollamaInitPromise) {
2626
this.ollamaInitPromise = (async () => {
2727
const dockerService = new (await import('./docker_service.js')).DockerService()
28-
const qdrantUrl = await dockerService.getServiceURL(DockerService.OLLAMA_SERVICE_NAME)
28+
const qdrantUrl = await dockerService.getServiceURL(SERVICE_NAMES.OLLAMA)
2929
if (!qdrantUrl) {
3030
throw new Error('Ollama service is not installed or running.')
3131
}
@@ -56,7 +56,7 @@ export class OllamaService {
5656
return new Promise(async (resolve) => {
5757
try {
5858
const dockerService = new (await import('./docker_service.js')).DockerService()
59-
const container = dockerService.docker.getContainer(DockerService.OLLAMA_SERVICE_NAME)
59+
const container = dockerService.docker.getContainer(SERVICE_NAMES.OLLAMA)
6060
if (!container) {
6161
logger.warn('[OllamaService] Ollama container is not running. Cannot download model.')
6262
resolve({
@@ -242,7 +242,7 @@ export class OllamaService {
242242

243243
const dockerService = new (await import('./docker_service.js')).DockerService()
244244

245-
const ollamAPIURL = await dockerService.getServiceURL(DockerService.OLLAMA_SERVICE_NAME)
245+
const ollamAPIURL = await dockerService.getServiceURL(SERVICE_NAMES.OLLAMA)
246246
if (!ollamAPIURL) {
247247
logger.warn('[OllamaService] Ollama service is not running. Cannot download model.')
248248
return {

admin/app/services/rag_service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { PDFParse } from 'pdf-parse'
99
import { createWorker } from 'tesseract.js'
1010
import { fromBuffer } from 'pdf2pic'
1111
import { OllamaService } from './ollama_service.js'
12+
import { SERVICE_NAMES } from '../../constants/service_names.js'
1213

1314
@inject()
1415
export class RagService {
@@ -26,7 +27,7 @@ export class RagService {
2627
private async _initializeQdrantClient() {
2728
if (!this.qdrantInitPromise) {
2829
this.qdrantInitPromise = (async () => {
29-
const qdrantUrl = await this.dockerService.getServiceURL(DockerService.QDRANT_SERVICE_NAME)
30+
const qdrantUrl = await this.dockerService.getServiceURL(SERVICE_NAMES.QDRANT)
3031
if (!qdrantUrl) {
3132
throw new Error('Qdrant service is not installed or running.')
3233
}

admin/app/services/zim_service.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import InstalledTier from '#models/installed_tier'
2626
import WikipediaSelection from '#models/wikipedia_selection'
2727
import { RunDownloadJob } from '#jobs/run_download_job'
2828
import { DownloadCollectionOperation, DownloadRemoteSuccessCallback } from '../../types/files.js'
29+
import { SERVICE_NAMES } from '../../constants/service_names.js'
2930

3031
const ZIM_MIME_TYPES = ['application/x-zim', 'application/x-openzim', 'application/octet-stream']
3132
const CATEGORIES_URL = 'https://raw.githubusercontent.com/Crosstalk-Solutions/project-nomad/refs/heads/master/collections/kiwix-categories.json'
@@ -243,7 +244,7 @@ export class ZimService implements IZimService {
243244
// Restart KIWIX container to pick up new ZIM file
244245
if (restart) {
245246
await this.dockerService
246-
.affectContainer(DockerService.KIWIX_SERVICE_NAME, 'restart')
247+
.affectContainer(SERVICE_NAMES.KIWIX, 'restart')
247248
.catch((error) => {
248249
logger.error(`[ZimService] Failed to restart KIWIX container:`, error) // Don't stop the download completion, just log the error.
249250
})
@@ -434,7 +435,7 @@ export class ZimService implements IZimService {
434435

435436
// Restart Kiwix to reflect the change
436437
await this.dockerService
437-
.affectContainer(DockerService.KIWIX_SERVICE_NAME, 'restart')
438+
.affectContainer(SERVICE_NAMES.KIWIX, 'restart')
438439
.catch((error) => {
439440
logger.error(`[ZimService] Failed to restart Kiwix after Wikipedia removal:`, error)
440441
})

admin/constants/service_names.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export const SERVICE_NAMES = {
2+
KIWIX: 'nomad_kiwix_server',
3+
OLLAMA: 'nomad_ollama',
4+
QDRANT: 'nomad_qdrant',
5+
CYBERCHEF: 'nomad_cyberchef',
6+
FLATNOTES: 'nomad_flatnotes',
7+
KOLIBRI: 'nomad_kolibri',
8+
}

admin/database/migrations/1769300000002_update_services_friendly_names.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class extends BaseSchema {
2727
UPDATE services SET
2828
friendly_name = 'AI Assistant',
2929
powered_by = 'Ollama',
30+
ui_location = '/chat',
3031
display_order = 3,
3132
description = 'Local AI chat that runs entirely on your hardware - no internet required'
3233
WHERE service_name = 'nomad_ollama'

admin/database/seeders/service_seeder.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Service from '#models/service'
2-
import { DockerService } from '#services/docker_service'
32
import { BaseSeeder } from '@adonisjs/lucid/seeders'
43
import { ModelAttributes } from '@adonisjs/lucid/types/model'
54
import env from '#start/env'
5+
import { SERVICE_NAMES } from '../../constants/service_names.js'
66

77
export default class ServiceSeeder extends BaseSeeder {
88
// Use environment variable with fallback to production default
@@ -15,7 +15,7 @@ export default class ServiceSeeder extends BaseSeeder {
1515
'created_at' | 'updated_at' | 'metadata' | 'id'
1616
>[] = [
1717
{
18-
service_name: DockerService.KIWIX_SERVICE_NAME,
18+
service_name: SERVICE_NAMES.KIWIX,
1919
friendly_name: 'Information Library',
2020
powered_by: 'Kiwix',
2121
display_order: 1,
@@ -39,7 +39,7 @@ export default class ServiceSeeder extends BaseSeeder {
3939
depends_on: null,
4040
},
4141
{
42-
service_name: DockerService.QDRANT_SERVICE_NAME,
42+
service_name: SERVICE_NAMES.QDRANT,
4343
friendly_name: 'Qdrant Vector Database',
4444
powered_by: null,
4545
display_order: 100, // Dependency service, not shown directly
@@ -62,7 +62,7 @@ export default class ServiceSeeder extends BaseSeeder {
6262
depends_on: null,
6363
},
6464
{
65-
service_name: DockerService.OLLAMA_SERVICE_NAME,
65+
service_name: SERVICE_NAMES.OLLAMA,
6666
friendly_name: 'AI Assistant',
6767
powered_by: 'Ollama',
6868
display_order: 3,
@@ -78,14 +78,14 @@ export default class ServiceSeeder extends BaseSeeder {
7878
},
7979
ExposedPorts: { '11434/tcp': {} },
8080
}),
81-
ui_location: null,
81+
ui_location: '/chat',
8282
installed: false,
8383
installation_status: 'idle',
8484
is_dependency_service: false,
85-
depends_on: DockerService.QDRANT_SERVICE_NAME,
85+
depends_on: SERVICE_NAMES.QDRANT,
8686
},
8787
{
88-
service_name: DockerService.CYBERCHEF_SERVICE_NAME,
88+
service_name: SERVICE_NAMES.CYBERCHEF,
8989
friendly_name: 'Data Tools',
9090
powered_by: 'CyberChef',
9191
display_order: 11,
@@ -107,7 +107,7 @@ export default class ServiceSeeder extends BaseSeeder {
107107
depends_on: null,
108108
},
109109
{
110-
service_name: DockerService.FLATNOTES_SERVICE_NAME,
110+
service_name: SERVICE_NAMES.FLATNOTES,
111111
friendly_name: 'Notes',
112112
powered_by: 'FlatNotes',
113113
display_order: 10,
@@ -131,7 +131,7 @@ export default class ServiceSeeder extends BaseSeeder {
131131
depends_on: null,
132132
},
133133
{
134-
service_name: DockerService.KOLIBRI_SERVICE_NAME,
134+
service_name: SERVICE_NAMES.KOLIBRI,
135135
friendly_name: 'Education Platform',
136136
powered_by: 'Kolibri',
137137
display_order: 2,

admin/inertia/lib/navigation.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ export function getServiceLink(ui_location: string): string {
1616
// If it's a port number, return a link to the service on that port
1717
return `http://${window.location.hostname}:${parsedPort}`;
1818
}
19-
// Otherwise, treat it as a path
19+
20+
const pathPattern = /^\/.+/;
21+
if (pathPattern.test(ui_location)) {
22+
// If it starts with a slash, treat it as a full path
23+
return ui_location;
24+
}
25+
2026
return `/${ui_location}`;
2127
}

admin/inertia/pages/easy-setup/index.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import useInternetStatus from '~/hooks/useInternetStatus'
1818
import { useSystemInfo } from '~/hooks/useSystemInfo'
1919
import classNames from 'classnames'
2020
import { CuratedCategory, CategoryTier, CategoryResource } from '../../../types/downloads'
21+
import { SERVICE_NAMES } from '../../../constants/service_names'
2122

2223
// Capability definitions - maps user-friendly categories to services
2324
interface Capability {
@@ -43,7 +44,7 @@ const CORE_CAPABILITIES: Capability[] = [
4344
'WikiHow articles and tutorials',
4445
'Project Gutenberg books and literature',
4546
],
46-
services: ['nomad_kiwix_serve'],
47+
services: [SERVICE_NAMES.KIWIX],
4748
icon: 'IconBooks',
4849
},
4950
{
@@ -57,7 +58,7 @@ const CORE_CAPABILITIES: Capability[] = [
5758
'Interactive exercises and quizzes',
5859
'Progress tracking for learners',
5960
],
60-
services: ['nomad_kolibri'],
61+
services: [SERVICE_NAMES.KOLIBRI],
6162
icon: 'IconSchool',
6263
},
6364
{
@@ -71,7 +72,7 @@ const CORE_CAPABILITIES: Capability[] = [
7172
'Ask questions, get help with writing, brainstorm ideas',
7273
'Runs on your own hardware with local AI models',
7374
],
74-
services: ['nomad_ollama'],
75+
services: [SERVICE_NAMES.OLLAMA],
7576
icon: 'IconRobot',
7677
},
7778
]
@@ -83,7 +84,7 @@ const ADDITIONAL_TOOLS: Capability[] = [
8384
technicalName: 'FlatNotes',
8485
description: 'Simple note-taking app with local storage',
8586
features: ['Markdown support', 'All notes stored locally', 'No account required'],
86-
services: ['nomad_flatnotes'],
87+
services: [SERVICE_NAMES.FLATNOTES],
8788
icon: 'IconNotes',
8889
},
8990
{
@@ -96,7 +97,7 @@ const ADDITIONAL_TOOLS: Capability[] = [
9697
'Encryption and hashing tools',
9798
'Data format conversion',
9899
],
99-
services: ['nomad_cyberchef'],
100+
services: [SERVICE_NAMES.CYBERCHEF],
100101
icon: 'IconChefHat',
101102
},
102103
]
@@ -804,10 +805,10 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim
804805

805806
const renderStep3 = () => {
806807
// Check if AI or Information capabilities are selected OR already installed
807-
const isAiSelected = selectedServices.includes('nomad_ollama') ||
808-
installedServices.some((s) => s.service_name === 'nomad_ollama')
809-
const isInformationSelected = selectedServices.includes('nomad_kiwix') ||
810-
installedServices.some((s) => s.service_name === 'nomad_kiwix')
808+
const isAiSelected = selectedServices.includes(SERVICE_NAMES.OLLAMA) ||
809+
installedServices.some((s) => s.service_name === SERVICE_NAMES.OLLAMA)
810+
const isInformationSelected = selectedServices.includes(SERVICE_NAMES.KIWIX) ||
811+
installedServices.some((s) => s.service_name === SERVICE_NAMES.KIWIX)
811812

812813
return (
813814
<div className="space-y-6">

0 commit comments

Comments
 (0)