src / workspaceRoot.ts
import { resolve } from "node:path";
import { AgenticError } from "./core/errors";
export interface WorkspaceRootSource {
getWorkingDirectory?: () => string | undefined;
}
/**
* LM Studio (0.4.15) creates a folder per chat under `<home>/working-directories/<id>`
* and hands it to every tools provider, so a setting that only applied "when
* the chat has no working directory" never applied at all: a fresh install
* always worked in an empty auto-created folder. That folder is recognised by
* shape — a run of digits directly under a `working-directories` parent.
*/
const AUTO_CHAT_DIRECTORY = /[\\/]working-directories[\\/]\d+[\\/]?$/;
export function isAutoCreatedChatDirectory(path: string): boolean {
return AUTO_CHAT_DIRECTORY.test(path.trim());
}
/**
* The workspace root both the preprocessor and the runtime use. A working
* directory the user picked for the chat wins; the configured workspace path
* wins over LM Studio's auto-created per-chat folder and over no directory at
* all; the auto-created folder itself is used only when nothing is configured.
*/
export function resolveWorkspaceRoot(ctl: WorkspaceRootSource, configuredWorkspacePath: string): string {
let fromController: string | undefined;
try {
const value = ctl.getWorkingDirectory?.();
fromController = typeof value === "string" && value.trim() ? value : undefined;
} catch {
fromController = undefined;
}
const configured = (configuredWorkspacePath ?? "").trim();
const workspace =
configured && (fromController === undefined || isAutoCreatedChatDirectory(fromController))
? configured
: (fromController ?? "");
if (!workspace.trim()) {
throw new AgenticError(
"INVALID_INPUT",
"No workspace is configured. Set the plugin's Workspace path, or give the chat a working directory.",
);
}
return resolve(workspace);
}
src / workspaceRoot.ts
import { resolve } from "node:path";
import { AgenticError } from "./core/errors";
export interface WorkspaceRootSource {
getWorkingDirectory?: () => string | undefined;
}
/**
* LM Studio (0.4.15) creates a folder per chat under `<home>/working-directories/<id>`
* and hands it to every tools provider, so a setting that only applied "when
* the chat has no working directory" never applied at all: a fresh install
* always worked in an empty auto-created folder. That folder is recognised by
* shape — a run of digits directly under a `working-directories` parent.
*/
const AUTO_CHAT_DIRECTORY = /[\\/]working-directories[\\/]\d+[\\/]?$/;
export function isAutoCreatedChatDirectory(path: string): boolean {
return AUTO_CHAT_DIRECTORY.test(path.trim());
}
/**
* The workspace root both the preprocessor and the runtime use. A working
* directory the user picked for the chat wins; the configured workspace path
* wins over LM Studio's auto-created per-chat folder and over no directory at
* all; the auto-created folder itself is used only when nothing is configured.
*/
export function resolveWorkspaceRoot(ctl: WorkspaceRootSource, configuredWorkspacePath: string): string {
let fromController: string | undefined;
try {
const value = ctl.getWorkingDirectory?.();
fromController = typeof value === "string" && value.trim() ? value : undefined;
} catch {
fromController = undefined;
}
const configured = (configuredWorkspacePath ?? "").trim();
const workspace =
configured && (fromController === undefined || isAutoCreatedChatDirectory(fromController))
? configured
: (fromController ?? "");
if (!workspace.trim()) {
throw new AgenticError(
"INVALID_INPUT",
"No workspace is configured. Set the plugin's Workspace path, or give the chat a working directory.",
);
}
return resolve(workspace);
}