Project Files
src / tools / refine.ts
import { tool, type Tool, type ToolsProviderController } from "@lmstudio/sdk";
import { z } from "zod";
import { RefineToolParamsShape, formatToolMetaBlock, setActiveChatContext, syncAttachmentsToState } from "../core-bundle.mjs";
import path from "path";
export function createRefineTool(ctl: ToolsProviderController): Tool {
return tool({
name: "refine",
description: `Refine the canvas via Draw Things image2image using model-specific refinement overlays.
Applies the model's dedicated refinement settings (low strength, preserves composition).
model is required — no auto-selection.
Model guidance:
- model: z-image produces a polished, refined look.
- model: qwen-image or model: flux produces a more natural, organic look.
Parameters:
- model: Required. Model preset to use for refinement.
- canvas: Source image. Notation: 'a1', 'v2', 'p1', 'i3'.
- width / height: Output dimensions (max 2048). Defaults to canvas dimensions.
- imageFormat: Target aspect ratio preset (e.g. '16:9', 'portrait'). Resolved to concrete pixel dimensions.
Returns: Inline preview, JSON with file URLs, model info, and clickable links.
${formatToolMetaBlock()}`,
parameters: RefineToolParamsShape as Record<string, z.ZodTypeAny>,
implementation: async (args: any, ctx: any) => {
const onProgress = (step: number, totalSteps: number | undefined, message?: string) => {
try {
if (step === -1 && message) { ctx.status(message); return; }
if (totalSteps && totalSteps > 0) {
ctx.status(`Step ${step}/${totalSteps} (${Math.round((step / (totalSteps + 1)) * 100)}%)`);
} else {
ctx.status(`Step ${step}...`);
}
} catch {}
};
try {
const workingDir = ctl.getWorkingDirectory();
if (typeof workingDir === "string" && workingDir.trim().length > 0) {
const chatId = path.basename(workingDir);
if (/^\d+$/.test(chatId)) {
setActiveChatContext({ chatId, workingDir, requestId: `tool-${Date.now()}` });
}
}
} catch {}
try {
const workingDir = ctl.getWorkingDirectory();
if (typeof workingDir === "string" && workingDir.trim().length > 0) {
await syncAttachmentsToState(workingDir, false, Number.MAX_SAFE_INTEGER);
}
} catch {}
const mod = await import("../core/tools.js");
const resp = await mod.handleRefine(args, onProgress);
if (resp && Array.isArray(resp.content)) return resp.content;
return typeof resp === "string" ? resp : JSON.stringify(resp);
},
});
}