feat(ollama): index 부팅 + IPC + preload + types (v0.2.3.1)
- index.ts: SettingsService.load() 후 endpoint/model 결정 (settings > env > default) - IPC: inbox:loadOllamaSettings + inbox:saveOllamaSettings - save: 임시 provider 로 healthCheck 통과 시에만 영속화 + holder.replace - 기존 in-flight generate 는 abort?.() (optional method) - preload + InboxApi shared types Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ import { ExportService } from './services/ExportService.js';
|
||||
import { ImportService } from './services/ImportService.js';
|
||||
import { SyncService } from './services/SyncService.js';
|
||||
import { TelemetryService } from './services/TelemetryService.js';
|
||||
import { SettingsService } from './services/SettingsService.js';
|
||||
|
||||
const HIDDEN_ARG = '--hidden';
|
||||
const startedHidden = process.argv.includes(HIDDEN_ARG);
|
||||
@@ -64,12 +65,23 @@ app.whenReady().then(async () => {
|
||||
const continuity = new ContinuityService(db);
|
||||
const intent = new IntentService(repo);
|
||||
|
||||
const resolvedEndpoint = process.env.INKLING_OLLAMA_ENDPOINT ?? 'http://localhost:11434';
|
||||
const settingsSvc = new SettingsService(paths.profileDir);
|
||||
const settings = await settingsSvc.load();
|
||||
|
||||
const resolvedEndpoint = settings.ollama?.endpoint
|
||||
?? process.env.INKLING_OLLAMA_ENDPOINT
|
||||
?? 'http://localhost:11434';
|
||||
const resolvedModel = settings.ollama?.model ?? 'gemma4:e4b';
|
||||
|
||||
logger.info('ai.endpoint', {
|
||||
endpoint: resolvedEndpoint,
|
||||
fromEnv: process.env.INKLING_OLLAMA_ENDPOINT !== undefined
|
||||
model: resolvedModel,
|
||||
source: settings.ollama?.endpoint
|
||||
? 'settings'
|
||||
: (process.env.INKLING_OLLAMA_ENDPOINT ? 'env' : 'default')
|
||||
});
|
||||
const provider = new LocalOllamaProvider({ endpoint: resolvedEndpoint });
|
||||
|
||||
const provider = new LocalOllamaProvider({ endpoint: resolvedEndpoint, model: resolvedModel });
|
||||
const providerHolder = new ProviderHolder(provider);
|
||||
const health = new HealthChecker(providerHolder, {
|
||||
onUpdate: (status) => {
|
||||
@@ -116,7 +128,7 @@ app.whenReady().then(async () => {
|
||||
registerCaptureApi(capture, getQuickCaptureWindow);
|
||||
registerInboxApi({
|
||||
repo, continuity, capture, health, intent,
|
||||
getInboxWindow
|
||||
getInboxWindow, settings: settingsSvc, providerHolder
|
||||
});
|
||||
|
||||
const hotkeys = new HotkeyService();
|
||||
|
||||
@@ -8,6 +8,9 @@ import type { HealthChecker } from '../services/HealthChecker.js';
|
||||
import type { IntentService } from '../services/IntentService.js';
|
||||
import type { Note } from '@shared/types';
|
||||
import type { HealthResult } from '../ai/InferenceProvider.js';
|
||||
import { LocalOllamaProvider } from '../ai/LocalOllamaProvider.js';
|
||||
import type { SettingsService } from '../services/SettingsService.js';
|
||||
import type { ProviderHolder } from '../ai/ProviderHolder.js';
|
||||
|
||||
export interface InboxIpcDeps {
|
||||
repo: NoteRepository;
|
||||
@@ -16,6 +19,8 @@ export interface InboxIpcDeps {
|
||||
health: HealthChecker;
|
||||
intent: IntentService;
|
||||
getInboxWindow: () => BrowserWindow | null;
|
||||
settings: SettingsService;
|
||||
providerHolder: ProviderHolder;
|
||||
}
|
||||
|
||||
export function registerInboxApi(deps: InboxIpcDeps): void {
|
||||
@@ -142,6 +147,23 @@ export function registerInboxApi(deps: InboxIpcDeps): void {
|
||||
ipcMain.handle('inbox:dismissRecall', (_e, id: string) => deps.capture.dismissRecall(id));
|
||||
ipcMain.handle('inbox:emitRecallShown', (_e, id: string) => deps.capture.emitRecallShown(id));
|
||||
ipcMain.handle('inbox:emitRecallSnoozed', (_e, id: string) => deps.capture.emitRecallSnoozed(id));
|
||||
|
||||
ipcMain.handle('inbox:loadOllamaSettings', async () => {
|
||||
const s = await deps.settings.load();
|
||||
return s.ollama ?? null;
|
||||
});
|
||||
|
||||
ipcMain.handle('inbox:saveOllamaSettings', async (_e, value: { endpoint: string; model: string }) => {
|
||||
// 검증: 새 인스턴스로 healthCheck
|
||||
const trial = new LocalOllamaProvider({ endpoint: value.endpoint, model: value.model });
|
||||
const r = await trial.healthCheck();
|
||||
if (!r.ok) return { ok: false, reason: r.reason ?? 'unknown' };
|
||||
await deps.settings.setOllama(value);
|
||||
deps.providerHolder.get().abort?.();
|
||||
deps.providerHolder.replace(trial);
|
||||
// HealthChecker 의 다음 polling cycle (~60s) 에 새 endpoint 반영
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
|
||||
export function pushNoteUpdated(getWin: () => BrowserWindow | null, note: Note): void {
|
||||
|
||||
@@ -44,7 +44,9 @@ const api: InklingApi = {
|
||||
markRecallOpened: (id: string) => ipcRenderer.invoke('inbox:markRecallOpened', id),
|
||||
dismissRecall: (id: string) => ipcRenderer.invoke('inbox:dismissRecall', id),
|
||||
emitRecallShown: (id: string) => ipcRenderer.invoke('inbox:emitRecallShown', id),
|
||||
emitRecallSnoozed: (id: string) => ipcRenderer.invoke('inbox:emitRecallSnoozed', id)
|
||||
emitRecallSnoozed: (id: string) => ipcRenderer.invoke('inbox:emitRecallSnoozed', id),
|
||||
loadOllamaSettings: () => ipcRenderer.invoke('inbox:loadOllamaSettings'),
|
||||
saveOllamaSettings: (v: { endpoint: string; model: string }) => ipcRenderer.invoke('inbox:saveOllamaSettings', v)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ export interface InboxApi {
|
||||
dismissRecall(id: string): Promise<{ note: Note }>;
|
||||
emitRecallShown(id: string): Promise<void>;
|
||||
emitRecallSnoozed(id: string): Promise<void>;
|
||||
loadOllamaSettings(): Promise<{ endpoint: string; model: string } | null>;
|
||||
saveOllamaSettings(v: { endpoint: string; model: string }): Promise<{ ok: true } | { ok: false; reason: string }>;
|
||||
}
|
||||
|
||||
export interface InklingApi {
|
||||
|
||||
Reference in New Issue
Block a user