Project Files
src / index.ts
import {type PluginContext} from "@lmstudio/sdk";
import {createDynamicConfig, CONFIG_KEYS, DEFAULT_EMBEDDING_MODELS} from "./config";
import {preprocess} from "./promptPreprocessor";
import {initLanguage, detectSystemLanguage, setLanguage, t} from "./i18n";
import fs from 'fs';
import path from 'path';
// 導出此變數,讓 promptPreprocessor.ts 找得到它
export let dynamicConfig: any;
export let pluginContext: PluginContext | null = null;
// 強制寫入 log(用於初始化階段診斷)
const forceLog = (msg: string, data?: any) => {
try {
const logPath = './logs/lmstudio-debug.log';
const log = `[${new Date().toISOString()}] ${msg}${data ? ' ' + JSON.stringify(data, null, 2) : ''}\n`;
const logDir = path.dirname(logPath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
fs.appendFileSync(logPath, log);
} catch (error) {
// 靜默失敗
}
};
// Debug 函數 - 支援從配置讀取設定
const debug = (msg: string, data?: any) => {
try {
// 檢查是否啟用 debug(優先使用配置,否則使用環境變數)
let enabled = false;
let logPath = './logs/lmstudio-debug.log';
if (pluginContext && dynamicConfig) {
try {
const config = (pluginContext as any).getPluginConfig?.(dynamicConfig);
if (config) {
enabled = config[CONFIG_KEYS.ENABLE_DEBUG] ?? false;
logPath = config[CONFIG_KEYS.DEBUG_LOG_PATH] ?? logPath;
}
} catch {
// 配置尚未載入,使用環境變數
enabled = process.env.DEBUG === 'true';
}
} else {
// 配置尚未載入,使用環境變數
enabled = process.env.DEBUG === 'true';
}
if (!enabled) {
return;
}
const log = `[${new Date().toISOString()}] ${msg}${data ? ' ' + JSON.stringify(data, null, 2) : ''}\n`;
// 確保目錄存在
const logDir = path.dirname(logPath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
fs.appendFileSync(logPath, log);
} catch (error) {
// 靜默失敗,避免 debug 功能干擾主程式
}
};
export async function main(context: PluginContext) {
// 儲存 context 供 debug 函數使用
pluginContext = context;
// 0. 檢測系統語言
try {
// Log system locale information for debugging
const systemLocale = Intl.DateTimeFormat().resolvedOptions().locale;
debug("System locale (Intl):", systemLocale);
debug("Environment LANG:", process.env.LANG || "not set");
debug("Environment LANGUAGE:", process.env.LANGUAGE || "not set");
debug("Environment LC_ALL:", process.env.LC_ALL || "not set");
} catch (e) {
debug("Failed to get system locale:", e);
}
const detectedLanguage = detectSystemLanguage();
debug("Detected system language:", detectedLanguage);
// 設定語言以取得翻譯文字
setLanguage(detectedLanguage);
const translations = t();
// 1. 先準備預設模型(僅在偵測失敗時使用)
let embeddingChoices: string[] = [...DEFAULT_EMBEDDING_MODELS];
// SDK 限制:PluginContext 沒有 client 屬性,無法在初始化時偵測已下載模型
// 只能使用預設模型列表,使用者需在 LM Studio 先下載模型
forceLog("使用預設 embedding 模型列表(SDK 限制:無法在 main() 中存取 client)");
forceLog("預設模型:", DEFAULT_EMBEDDING_MODELS);
// 4. 動態生成配置介面(帶語言參數)
dynamicConfig = createDynamicConfig(embeddingChoices, detectedLanguage);
context.withConfigSchematics(dynamicConfig);
context.withPromptPreprocessor(preprocess);
}