mirror of
https://github.com/lmstudio-ai/lms.git
synced 2025-09-22 17:24:32 +08:00
Remove dot cache assumption (#124)
This commit is contained in:
14
README.md
14
README.md
@ -16,19 +16,7 @@
|
|||||||
|
|
||||||
`lms` ships with [LM Studio](https://lmstudio.ai/) 0.2.22 and newer.
|
`lms` ships with [LM Studio](https://lmstudio.ai/) 0.2.22 and newer.
|
||||||
|
|
||||||
To set it up, run the built-in `bootstrap` command like so:
|
If you have trouble running the command, try running `npx lmstudio install-cli` to add it to path.
|
||||||
|
|
||||||
- **Windows**:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cmd /c %USERPROFILE%/.cache/lm-studio/bin/lms.exe bootstrap
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Linux/macOS**:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
~/.cache/lm-studio/bin/lms bootstrap
|
|
||||||
```
|
|
||||||
|
|
||||||
To check if the bootstrapping was successful, run the following in a **👉 new terminal window 👈**:
|
To check if the bootstrapping was successful, run the following in a **👉 new terminal window 👈**:
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lmstudio/lms-common": "^0.7.3",
|
"@lmstudio/lms-common": "^0.7.3",
|
||||||
|
"@lmstudio/lms-common-server": "^0.2.3",
|
||||||
"@lmstudio/lms-es-plugin-runner": "^0.0.5",
|
"@lmstudio/lms-es-plugin-runner": "^0.0.5",
|
||||||
"@lmstudio/lms-isomorphic": "^0.4.2",
|
"@lmstudio/lms-isomorphic": "^0.4.2",
|
||||||
"@lmstudio/lms-lmstudio": "^0.0.17",
|
"@lmstudio/lms-lmstudio": "^0.0.17",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { SimpleLogger } from "@lmstudio/lms-common";
|
import { SimpleLogger } from "@lmstudio/lms-common";
|
||||||
import os from "os";
|
|
||||||
import path from "path";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { SimpleFileData } from "./SimpleFileData.js";
|
import { SimpleFileData } from "./SimpleFileData.js";
|
||||||
|
import { cliPrefPath } from "./lmstudioPaths.js";
|
||||||
|
|
||||||
export async function getCliPref(logger?: SimpleLogger) {
|
export async function getCliPref(logger?: SimpleLogger) {
|
||||||
const cliPrefSchema = z.object({
|
const cliPrefSchema = z.object({
|
||||||
@ -19,7 +18,7 @@ export async function getCliPref(logger?: SimpleLogger) {
|
|||||||
autoStartServer: undefined,
|
autoStartServer: undefined,
|
||||||
};
|
};
|
||||||
const cliPref = new SimpleFileData(
|
const cliPref = new SimpleFileData(
|
||||||
path.join(os.homedir(), ".cache/lm-studio/.internal/cli-pref.json"),
|
cliPrefPath,
|
||||||
defaultCliPref,
|
defaultCliPref,
|
||||||
cliPrefSchema,
|
cliPrefSchema,
|
||||||
new SimpleLogger("CliPref", logger),
|
new SimpleLogger("CliPref", logger),
|
||||||
|
@ -5,9 +5,7 @@ import { spawn } from "child_process";
|
|||||||
import { option, optional, string } from "cmd-ts";
|
import { option, optional, string } from "cmd-ts";
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
import { readFile } from "fs/promises";
|
import { readFile } from "fs/promises";
|
||||||
import { homedir } from "os";
|
import { appInstallLocationFilePath, lmsKey2Path } from "./lmstudioPaths.js";
|
||||||
import path from "path";
|
|
||||||
import { lmsKey2Path } from "./lmstudioPaths.js";
|
|
||||||
import { type LogLevelArgs } from "./logLevel.js";
|
import { type LogLevelArgs } from "./logLevel.js";
|
||||||
import { checkHttpServer } from "./subcommands/server.js";
|
import { checkHttpServer } from "./subcommands/server.js";
|
||||||
import { refinedNumber } from "./types/refinedNumber.js";
|
import { refinedNumber } from "./types/refinedNumber.js";
|
||||||
@ -64,13 +62,9 @@ async function tryFindLocalAPIServer(): Promise<number | null> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppInstallLocationPath() {
|
|
||||||
return path.join(homedir(), ".cache/lm-studio/.internal/app-install-location.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function wakeUpService(logger: SimpleLogger): Promise<boolean> {
|
export async function wakeUpService(logger: SimpleLogger): Promise<boolean> {
|
||||||
logger.info("Waking up LM Studio service...");
|
logger.info("Waking up LM Studio service...");
|
||||||
const appInstallLocationPath = getAppInstallLocationPath();
|
const appInstallLocationPath = appInstallLocationFilePath;
|
||||||
logger.debug(`Resolved appInstallLocationPath: ${appInstallLocationPath}`);
|
logger.debug(`Resolved appInstallLocationPath: ${appInstallLocationPath}`);
|
||||||
try {
|
try {
|
||||||
const appInstallLocation = JSON.parse(
|
const appInstallLocation = JSON.parse(
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
import { homedir } from "os";
|
import { findLMStudioHome } from "@lmstudio/lms-common-server";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
export const pluginsFolderPath = join(homedir(), ".cache", "lm-studio", "extensions", "plugins");
|
const lmstudioHome = findLMStudioHome();
|
||||||
export const lmsKey2Path = join(homedir(), ".cache", "lm-studio", ".internal", "lms-key-2");
|
export const pluginsFolderPath = join(lmstudioHome, "extensions", "plugins");
|
||||||
|
export const lmsKey2Path = join(lmstudioHome, ".internal", "lms-key-2");
|
||||||
|
export const cliPrefPath = join(lmstudioHome, ".internal", "cli-pref.json");
|
||||||
|
export const appInstallLocationFilePath = join(
|
||||||
|
lmstudioHome,
|
||||||
|
".internal",
|
||||||
|
"app-install-location.json",
|
||||||
|
);
|
||||||
|
export const defaultModelsFolder = join(lmstudioHome, "models");
|
||||||
|
export const serverCtlPath = join(lmstudioHome, ".internal", "http-server-ctl.json");
|
||||||
|
export const serverConfigPath = join(lmstudioHome, ".internal", "http-server-config.json");
|
||||||
|
@ -17,6 +17,7 @@ import { homedir } from "os";
|
|||||||
import { basename, dirname, join } from "path";
|
import { basename, dirname, join } from "path";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { getCliPref } from "../cliPref.js";
|
import { getCliPref } from "../cliPref.js";
|
||||||
|
import { defaultModelsFolder } from "../lmstudioPaths.js";
|
||||||
import { createLogger, logLevelArgs } from "../logLevel.js";
|
import { createLogger, logLevelArgs } from "../logLevel.js";
|
||||||
|
|
||||||
const userRepoType: Type<string, [string, string]> = {
|
const userRepoType: Type<string, [string, string]> = {
|
||||||
@ -327,7 +328,7 @@ async function locateSettingsJson(logger: SimpleLogger) {
|
|||||||
*/
|
*/
|
||||||
async function resolveModelsFolderPath(logger: SimpleLogger) {
|
async function resolveModelsFolderPath(logger: SimpleLogger) {
|
||||||
const settingsJsonPath = await locateSettingsJson(logger);
|
const settingsJsonPath = await locateSettingsJson(logger);
|
||||||
let modelsFolderPath = join(homedir(), ".cache", "lm-studio", "models");
|
let modelsFolderPath = defaultModelsFolder;
|
||||||
if (settingsJsonPath === null) {
|
if (settingsJsonPath === null) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"Could not locate LM Studio configuration file, using default path:",
|
"Could not locate LM Studio configuration file, using default path:",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { text, type SimpleLogger } from "@lmstudio/lms-common";
|
import { text, type SimpleLogger } from "@lmstudio/lms-common";
|
||||||
import { command, flag, number, option, optional, subcommands } from "cmd-ts";
|
import { command, flag, number, option, optional, subcommands } from "cmd-ts";
|
||||||
import { mkdir, readFile, writeFile } from "fs/promises";
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
||||||
import os from "os";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { wakeUpService } from "../createClient.js";
|
import { wakeUpService } from "../createClient.js";
|
||||||
|
import { serverConfigPath, serverCtlPath } from "../lmstudioPaths.js";
|
||||||
import { createLogger, logLevelArgs } from "../logLevel.js";
|
import { createLogger, logLevelArgs } from "../logLevel.js";
|
||||||
|
|
||||||
type HttpServerCtl =
|
type HttpServerCtl =
|
||||||
@ -20,19 +20,10 @@ interface HttpServerConfig {
|
|||||||
port: number;
|
port: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerCtlPath() {
|
|
||||||
return path.join(os.homedir(), ".cache/lm-studio/.internal/http-server-ctl.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getServerConfigPath() {
|
|
||||||
return path.join(os.homedir(), ".cache/lm-studio/.internal/http-server-config.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a control object to the server control file.
|
* Write a control object to the server control file.
|
||||||
*/
|
*/
|
||||||
async function writeToServerCtl(logger: SimpleLogger, controlObject: HttpServerCtl) {
|
async function writeToServerCtl(logger: SimpleLogger, controlObject: HttpServerCtl) {
|
||||||
const serverCtlPath = getServerCtlPath();
|
|
||||||
logger.debug(`Resolved serverCtlPath: ${serverCtlPath}`);
|
logger.debug(`Resolved serverCtlPath: ${serverCtlPath}`);
|
||||||
const dir = path.dirname(serverCtlPath);
|
const dir = path.dirname(serverCtlPath);
|
||||||
logger.debug(`Making sure directory exists: ${dir}`);
|
logger.debug(`Making sure directory exists: ${dir}`);
|
||||||
@ -51,7 +42,7 @@ async function waitForCtlFileClear(
|
|||||||
) {
|
) {
|
||||||
for (let i = 0; i < maxAttempts; i++) {
|
for (let i = 0; i < maxAttempts; i++) {
|
||||||
await new Promise(resolve => setTimeout(resolve, checkIntervalMs));
|
await new Promise(resolve => setTimeout(resolve, checkIntervalMs));
|
||||||
const isEmpty = (await readFile(getServerCtlPath(), "utf-8")).length === 0;
|
const isEmpty = (await readFile(serverCtlPath, "utf-8")).length === 0;
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
logger.debug(`Attempt ${i + 1}: File has been cleared`);
|
logger.debug(`Attempt ${i + 1}: File has been cleared`);
|
||||||
return true;
|
return true;
|
||||||
@ -112,7 +103,7 @@ async function checkHttpServerWithRetries(logger: SimpleLogger, port: number, ma
|
|||||||
* Gets the last status of the server.
|
* Gets the last status of the server.
|
||||||
*/
|
*/
|
||||||
export async function getServerConfig(logger: SimpleLogger) {
|
export async function getServerConfig(logger: SimpleLogger) {
|
||||||
const lastStatusPath = getServerConfigPath();
|
const lastStatusPath = serverConfigPath;
|
||||||
logger.debug(`Reading last status from ${lastStatusPath}`);
|
logger.debug(`Reading last status from ${lastStatusPath}`);
|
||||||
const lastStatus = JSON.parse(await readFile(lastStatusPath, "utf-8")) as HttpServerConfig;
|
const lastStatus = JSON.parse(await readFile(lastStatusPath, "utf-8")) as HttpServerConfig;
|
||||||
return lastStatus;
|
return lastStatus;
|
||||||
|
Reference in New Issue
Block a user