dist-mcp / mcp / scratchpadResolution.js
import fs from "node:fs/promises";
import path from "node:path";
import { ensureMediaState, resolveScratchpadFolder, scratchpadFolderRemediation } from "./core-bundle.mjs";
import { logger } from "./mcpLogger.js";
/**
* scratchpadFolder is optional only for the generic preset (falls back to
* chatWorkingDirectories itself when omitted). The bionic preset requires an
* explicit scratchpadFolder — pass requireFolder=true there — since analyse_image's
* HTML preview and detect_object/annotate_image's report/preview files are meant to
* live in a per-session folder, not directly in the shared chatWorkingDirectories root.
*/
export async function resolveEffectiveScratchpadPath(chatWorkingDirectories, requestedFolder, requireFolder = false, preset) {
const requested = typeof requestedFolder === "string" ? requestedFolder.trim() : "";
if (requested) {
return resolveScratchpadFolder(chatWorkingDirectories, requested, logger);
}
if (requireFolder) {
throw new Error(`scratchpadFolder is required. ${scratchpadFolderRemediation(preset)}`);
}
const basePath = path.resolve(chatWorkingDirectories);
let stats;
try {
stats = await fs.stat(basePath);
}
catch (error) {
throw new Error(`CHAT_WORKING_DIRECTORIES is not accessible: ${basePath} (${error instanceof Error ? error.message : String(error)})`);
}
if (!stats.isDirectory()) {
throw new Error(`CHAT_WORKING_DIRECTORIES is not a directory: ${basePath}`);
}
await ensureMediaState(basePath);
return basePath;
}
dist-mcp / mcp / scratchpadResolution.js
import fs from "node:fs/promises";
import path from "node:path";
import { ensureMediaState, resolveScratchpadFolder, scratchpadFolderRemediation } from "./core-bundle.mjs";
import { logger } from "./mcpLogger.js";
/**
* scratchpadFolder is optional only for the generic preset (falls back to
* chatWorkingDirectories itself when omitted). The bionic preset requires an
* explicit scratchpadFolder — pass requireFolder=true there — since analyse_image's
* HTML preview and detect_object/annotate_image's report/preview files are meant to
* live in a per-session folder, not directly in the shared chatWorkingDirectories root.
*/
export async function resolveEffectiveScratchpadPath(chatWorkingDirectories, requestedFolder, requireFolder = false, preset) {
const requested = typeof requestedFolder === "string" ? requestedFolder.trim() : "";
if (requested) {
return resolveScratchpadFolder(chatWorkingDirectories, requested, logger);
}
if (requireFolder) {
throw new Error(`scratchpadFolder is required. ${scratchpadFolderRemediation(preset)}`);
}
const basePath = path.resolve(chatWorkingDirectories);
let stats;
try {
stats = await fs.stat(basePath);
}
catch (error) {
throw new Error(`CHAT_WORKING_DIRECTORIES is not accessible: ${basePath} (${error instanceof Error ? error.message : String(error)})`);
}
if (!stats.isDirectory()) {
throw new Error(`CHAT_WORKING_DIRECTORIES is not a directory: ${basePath}`);
}
await ensureMediaState(basePath);
return basePath;
}