feat: added local LLM context length option

This commit is contained in:
Xiaohan-Tian
2026-05-14 19:44:25 -07:00
parent dbf0c20542
commit a48966d761
13 changed files with 467 additions and 4 deletions
@@ -2,6 +2,7 @@ import { KGConfigStorage } from '../io/KGConfigStorage';
import { CONFIG_UPGRADER_CONSTANTS } from '../../constants/coreConstants';
import { upgradeConfigToV1 } from './upgradeConfigToV1';
import { upgradeConfigToV2 } from './upgradeConfigToV2';
import { upgradeConfigToV3 } from './upgradeConfigToV3';
/**
* KGConfigUpgrader — Orchestrates app-level migrations (e.g., storage backend changes).
@@ -38,6 +39,10 @@ export class KGConfigUpgrader {
await upgradeConfigToV2();
break;
}
case 3: {
await upgradeConfigToV3();
break;
}
default: {
throw new Error(`No config upgrader found for version ${nextVersion}`);
}
@@ -0,0 +1,88 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
const configStore = new Map<string, { name: string; data: Record<string, unknown>; lastModified: number }>();
vi.mock('../io/KGConfigStorage', () => ({
KGConfigStorage: {
getInstance: () => ({
getRaw: vi.fn(async (name: string) => configStore.get(name)?.data ?? null),
saveRaw: vi.fn(async (name: string, data: Record<string, unknown>) => {
configStore.set(name, { name, data, lastModified: Date.now() });
}),
}),
},
}));
import { upgradeConfigToV3 } from './upgradeConfigToV3';
describe('upgradeConfigToV3', () => {
beforeEach(() => {
configStore.clear();
});
it('adds the default local browser context length when missing', async () => {
configStore.set('userConfig', {
name: 'userConfig',
data: {
general: {
llm_provider: 'local_browser',
},
},
lastModified: Date.now(),
});
await upgradeConfigToV3();
expect(
((configStore.get('userConfig')?.data.general as Record<string, unknown>).local_browser as Record<string, unknown>).context_length,
).toBe(32768);
});
it.each([32768, 65536, 131072])('preserves existing context length %s', async (existingValue) => {
configStore.set('userConfig', {
name: 'userConfig',
data: {
general: {
local_browser: {
context_length: existingValue,
},
},
},
lastModified: Date.now(),
});
await upgradeConfigToV3();
expect(
((configStore.get('userConfig')?.data.general as Record<string, unknown>).local_browser as Record<string, unknown>).context_length,
).toBe(existingValue);
});
it('is a no-op when general is missing', async () => {
configStore.set('userConfig', {
name: 'userConfig',
data: {},
lastModified: Date.now(),
});
await upgradeConfigToV3();
expect(configStore.get('userConfig')?.data).toEqual({});
});
it('is a no-op when general is malformed', async () => {
configStore.set('userConfig', {
name: 'userConfig',
data: {
general: 'invalid',
},
lastModified: Date.now(),
});
await upgradeConfigToV3();
expect(configStore.get('userConfig')?.data).toEqual({
general: 'invalid',
});
});
});
@@ -0,0 +1,35 @@
import { KGConfigStorage } from '../io/KGConfigStorage';
import { LOCAL_LLM_DEFAULT_CONTEXT_LENGTH } from '../../util/localLLMConfig';
const CONFIG_KEY = 'userConfig';
export async function upgradeConfigToV3(): Promise<void> {
const storage = KGConfigStorage.getInstance();
const rawConfig = await storage.getRaw(CONFIG_KEY);
if (!rawConfig || typeof rawConfig !== 'object') {
return;
}
const config = rawConfig as Record<string, unknown>;
const general = config.general;
if (!general || typeof general !== 'object') {
return;
}
const generalRecord = general as Record<string, unknown>;
const localBrowser = generalRecord.local_browser;
if (!localBrowser || typeof localBrowser !== 'object') {
generalRecord.local_browser = { context_length: LOCAL_LLM_DEFAULT_CONTEXT_LENGTH };
await storage.saveRaw(CONFIG_KEY, config);
return;
}
const localBrowserRecord = localBrowser as Record<string, unknown>;
if ('context_length' in localBrowserRecord) {
return;
}
localBrowserRecord.context_length = LOCAL_LLM_DEFAULT_CONTEXT_LENGTH;
await storage.saveRaw(CONFIG_KEY, config);
}
+6
View File
@@ -8,6 +8,9 @@ interface AppConfig {
language: string;
llm_provider: 'local_browser' | 'openai' | 'gemini' | 'claude' | 'claude_openrouter' | 'openai_compatible';
persist_api_keys_non_localhost: boolean;
local_browser: {
context_length: 32768 | 65536 | 131072;
};
openai: {
api_key: string;
flex: boolean;
@@ -208,6 +211,9 @@ export class ConfigManager {
base_url: '',
model: ''
},
local_browser: {
context_length: 32768
},
soundfont: {
base_url: 'https://cdn.jsdelivr.net/npm/soundfont-for-samplers/FluidR3_GM/'
},