src / config.ts
import { createConfigSchematics, type InferParsedConfig } from "@lmstudio/sdk";
/* -------------------------------------------------------------------------- */
/* SHARTI Connector Config */
/* */
/* Order: Connection → Sampling → Reasoning → Tools → Request → Diagnostics */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Canonical default values (single source of truth) */
/* */
/* Declared ONCE here and referenced both by the schema below (UI defaults) */
/* and by the coercion fallbacks in request.ts / generator.ts. Changing a */
/* default therefore touches exactly one place. */
/* -------------------------------------------------------------------------- */
export const CONFIG_DEFAULTS = {
// Sampling
temperature: 1.0,
topK: 20,
topP: 0.95,
minP: 0,
presencePenalty: 0,
frequencyPenalty: 0,
repetitionPenalty: 1,
seed: -1,
maxTokens: 4000,
// Reasoning
reasoningEffort: "default",
thinkingTokenBudget: -1,
// Tools
toolChoice: "auto",
parallelToolCalls: false,
// Request
priority: "normal",
timeout: 0,
maxRetries: 3,
// Diagnostics
logLevel: "normal",
showTurnSummaryInChat: true,
// Feature toggles
customSampling: true,
} as const;
export const configSchematics = createConfigSchematics()
/* ─── Connection ─── */
.field(
"baseUrl",
"string",
{
displayName: "Base URL",
subtitle: "Base URL for the OpenAI-compatible API endpoint.",
placeholder: "https://api.sharti.ru/v1",
},
"",
)
.field(
"apiKey",
"string",
{
displayName: "API Key",
subtitle: "Leave empty if the endpoint does not require authentication.",
isProtected: true,
placeholder: "sharti-...",
},
"",
)
.field(
"model",
"string",
{
displayName: "Model",
subtitle: "Name of the model to use for generation.",
placeholder: "Qwen3.8-27B",
},
"",
)
/* ─── Sampling ─── */
.field(
"customSampling",
"boolean",
{
displayName: "Custom Sampling",
subtitle: "When off, the following are not sent: Temperature, Top K, Top P, Min P, Presence Penalty, Frequency Penalty, Repetition Penalty, Seed, Max Tokens, Reasoning Effort, Thinking Token Budget.",
},
CONFIG_DEFAULTS.customSampling,
)
.field(
"temperature",
"numeric",
{
displayName: "Temperature",
subtitle: "Sampling temperature (0 to 2).",
min: 0,
max: 2,
slider: { min: 0, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.temperature,
)
.field(
"topK",
"numeric",
{
displayName: "Top K",
subtitle: "Number of highest-probability tokens (0 to 100).",
min: -1,
max: 100,
int: true,
slider: { min: 0, max: 100, step: 1 },
},
CONFIG_DEFAULTS.topK,
)
.field(
"topP",
"numeric",
{
displayName: "Top P",
subtitle: "Nucleus sampling threshold (0 to 1).",
min: 0,
max: 1,
slider: { min: 0, max: 1, step: 0.01 },
},
CONFIG_DEFAULTS.topP,
)
.field(
"minP",
"numeric",
{
displayName: "Min P",
subtitle: "Minimum probability threshold (0 to 1).",
min: 0,
max: 1,
slider: { min: 0, max: 1, step: 0.01 },
},
CONFIG_DEFAULTS.minP,
)
.field(
"presencePenalty",
"numeric",
{
displayName: "Presence Penalty",
subtitle: "Penalizes tokens that already appear (-2 to 2).",
min: -2,
max: 2,
slider: { min: -2, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.presencePenalty,
)
.field(
"frequencyPenalty",
"numeric",
{
displayName: "Frequency Penalty",
subtitle: "Penalizes tokens by frequency (-2 to 2).",
min: -2,
max: 2,
slider: { min: -2, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.frequencyPenalty,
)
.field(
"repetitionPenalty",
"numeric",
{
displayName: "Repetition Penalty",
subtitle: "Penalizes repeated tokens (0.1 to 2).",
min: 0.1,
max: 2,
slider: { min: 0.1, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.repetitionPenalty,
)
.field(
"seed",
"numeric",
{
displayName: "Seed",
subtitle: "Random seed for reproducibility (-1 = random).",
min: -1,
max: 999999999,
int: true,
},
CONFIG_DEFAULTS.seed,
)
.field(
"maxTokens",
"numeric",
{
displayName: "Max Tokens",
subtitle: "Maximum number of tokens to generate.",
min: 0,
max: 128000,
int: true,
slider: { min: 0, max: 128000, step: 250 },
},
CONFIG_DEFAULTS.maxTokens,
)
/* ─── Reasoning ─── */
.field(
"reasoningEffort",
"select",
{
displayName: "Reasoning Effort",
subtitle: "Provider-specific reasoning level.",
options: [
{ value: "default", displayName: "Default" },
{ value: "none", displayName: "None" },
{ value: "minimal", displayName: "Minimal" },
{ value: "low", displayName: "Low" },
{ value: "medium", displayName: "Medium" },
{ value: "high", displayName: "High" },
{ value: "xhigh", displayName: "XHigh" },
{ value: "max", displayName: "Max" },
],
},
CONFIG_DEFAULTS.reasoningEffort,
)
.field(
"thinkingTokenBudget",
"numeric",
{
displayName: "Thinking Token Budget",
subtitle: "Max thinking tokens (-1 = no cap).",
min: -1,
max: 128000,
int: true,
},
CONFIG_DEFAULTS.thinkingTokenBudget,
)
/* ─── Tools ─── */
.field(
"toolChoice",
"select",
{
displayName: "Tool Choice",
subtitle: "How to handle tool calls.",
options: [
{ value: "auto", displayName: "Auto" },
{ value: "required", displayName: "Required" },
{ value: "none", displayName: "None" },
],
},
CONFIG_DEFAULTS.toolChoice,
)
.field(
"parallelToolCalls",
"boolean",
{
displayName: "Parallel Tool Calls",
subtitle: "Allow the model to make parallel tool calls.",
},
CONFIG_DEFAULTS.parallelToolCalls,
)
/* ─── Request ─── */
.field(
"priority",
"select",
{
displayName: "Priority",
subtitle: "Request priority in the provider queue.",
options: [
{ value: "foreground", displayName: "Foreground" },
{ value: "normal", displayName: "Normal" },
{ value: "background", displayName: "Background" },
],
},
CONFIG_DEFAULTS.priority,
)
.field(
"timeout",
"numeric",
{
displayName: "Request Timeout (s)",
subtitle: "Max seconds a request may take (0 = no timeout).",
min: 0,
max: 600,
int: true,
},
CONFIG_DEFAULTS.timeout,
)
.field(
"maxRetries",
"numeric",
{
displayName: "Max Retries",
subtitle: "Retry attempts on 503 (0 to 5).",
min: 0,
max: 5,
int: true,
},
CONFIG_DEFAULTS.maxRetries,
)
/* ─── Diagnostics ─── */
.field(
"logLevel",
"select",
{
displayName: "Log Level",
subtitle: "Controls verbosity of diagnostic output in the developer console. Errors and warnings are always shown.",
options: [
{ value: "minimal", displayName: "Minimal" },
{ value: "normal", displayName: "Normal" },
{ value: "debug", displayName: "Debug" },
],
},
CONFIG_DEFAULTS.logLevel,
)
.field(
"showTurnSummaryInChat",
"boolean",
{
displayName: "Show Turn Summary in Chat",
subtitle: "Display the aggregated turn summary at the end of the response in the chat window.",
},
CONFIG_DEFAULTS.showTurnSummaryInChat,
)
.build();
/** Strongly-typed view of the resolved plugin configuration (derived from the schematics). */
export type ShartiConfig = InferParsedConfig<typeof configSchematics>;
src / config.ts
import { createConfigSchematics, type InferParsedConfig } from "@lmstudio/sdk";
/* -------------------------------------------------------------------------- */
/* SHARTI Connector Config */
/* */
/* Order: Connection → Sampling → Reasoning → Tools → Request → Diagnostics */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Canonical default values (single source of truth) */
/* */
/* Declared ONCE here and referenced both by the schema below (UI defaults) */
/* and by the coercion fallbacks in request.ts / generator.ts. Changing a */
/* default therefore touches exactly one place. */
/* -------------------------------------------------------------------------- */
export const CONFIG_DEFAULTS = {
// Sampling
temperature: 1.0,
topK: 20,
topP: 0.95,
minP: 0,
presencePenalty: 0,
frequencyPenalty: 0,
repetitionPenalty: 1,
seed: -1,
maxTokens: 4000,
// Reasoning
reasoningEffort: "default",
thinkingTokenBudget: -1,
// Tools
toolChoice: "auto",
parallelToolCalls: false,
// Request
priority: "normal",
timeout: 0,
maxRetries: 3,
// Diagnostics
logLevel: "normal",
showTurnSummaryInChat: true,
// Feature toggles
customSampling: true,
} as const;
export const configSchematics = createConfigSchematics()
/* ─── Connection ─── */
.field(
"baseUrl",
"string",
{
displayName: "Base URL",
subtitle: "Base URL for the OpenAI-compatible API endpoint.",
placeholder: "https://api.sharti.ru/v1",
},
"",
)
.field(
"apiKey",
"string",
{
displayName: "API Key",
subtitle: "Leave empty if the endpoint does not require authentication.",
isProtected: true,
placeholder: "sharti-...",
},
"",
)
.field(
"model",
"string",
{
displayName: "Model",
subtitle: "Name of the model to use for generation.",
placeholder: "Qwen3.8-27B",
},
"",
)
/* ─── Sampling ─── */
.field(
"customSampling",
"boolean",
{
displayName: "Custom Sampling",
subtitle: "When off, the following are not sent: Temperature, Top K, Top P, Min P, Presence Penalty, Frequency Penalty, Repetition Penalty, Seed, Max Tokens, Reasoning Effort, Thinking Token Budget.",
},
CONFIG_DEFAULTS.customSampling,
)
.field(
"temperature",
"numeric",
{
displayName: "Temperature",
subtitle: "Sampling temperature (0 to 2).",
min: 0,
max: 2,
slider: { min: 0, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.temperature,
)
.field(
"topK",
"numeric",
{
displayName: "Top K",
subtitle: "Number of highest-probability tokens (0 to 100).",
min: -1,
max: 100,
int: true,
slider: { min: 0, max: 100, step: 1 },
},
CONFIG_DEFAULTS.topK,
)
.field(
"topP",
"numeric",
{
displayName: "Top P",
subtitle: "Nucleus sampling threshold (0 to 1).",
min: 0,
max: 1,
slider: { min: 0, max: 1, step: 0.01 },
},
CONFIG_DEFAULTS.topP,
)
.field(
"minP",
"numeric",
{
displayName: "Min P",
subtitle: "Minimum probability threshold (0 to 1).",
min: 0,
max: 1,
slider: { min: 0, max: 1, step: 0.01 },
},
CONFIG_DEFAULTS.minP,
)
.field(
"presencePenalty",
"numeric",
{
displayName: "Presence Penalty",
subtitle: "Penalizes tokens that already appear (-2 to 2).",
min: -2,
max: 2,
slider: { min: -2, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.presencePenalty,
)
.field(
"frequencyPenalty",
"numeric",
{
displayName: "Frequency Penalty",
subtitle: "Penalizes tokens by frequency (-2 to 2).",
min: -2,
max: 2,
slider: { min: -2, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.frequencyPenalty,
)
.field(
"repetitionPenalty",
"numeric",
{
displayName: "Repetition Penalty",
subtitle: "Penalizes repeated tokens (0.1 to 2).",
min: 0.1,
max: 2,
slider: { min: 0.1, max: 2, step: 0.01 },
},
CONFIG_DEFAULTS.repetitionPenalty,
)
.field(
"seed",
"numeric",
{
displayName: "Seed",
subtitle: "Random seed for reproducibility (-1 = random).",
min: -1,
max: 999999999,
int: true,
},
CONFIG_DEFAULTS.seed,
)
.field(
"maxTokens",
"numeric",
{
displayName: "Max Tokens",
subtitle: "Maximum number of tokens to generate.",
min: 0,
max: 128000,
int: true,
slider: { min: 0, max: 128000, step: 250 },
},
CONFIG_DEFAULTS.maxTokens,
)
/* ─── Reasoning ─── */
.field(
"reasoningEffort",
"select",
{
displayName: "Reasoning Effort",
subtitle: "Provider-specific reasoning level.",
options: [
{ value: "default", displayName: "Default" },
{ value: "none", displayName: "None" },
{ value: "minimal", displayName: "Minimal" },
{ value: "low", displayName: "Low" },
{ value: "medium", displayName: "Medium" },
{ value: "high", displayName: "High" },
{ value: "xhigh", displayName: "XHigh" },
{ value: "max", displayName: "Max" },
],
},
CONFIG_DEFAULTS.reasoningEffort,
)
.field(
"thinkingTokenBudget",
"numeric",
{
displayName: "Thinking Token Budget",
subtitle: "Max thinking tokens (-1 = no cap).",
min: -1,
max: 128000,
int: true,
},
CONFIG_DEFAULTS.thinkingTokenBudget,
)
/* ─── Tools ─── */
.field(
"toolChoice",
"select",
{
displayName: "Tool Choice",
subtitle: "How to handle tool calls.",
options: [
{ value: "auto", displayName: "Auto" },
{ value: "required", displayName: "Required" },
{ value: "none", displayName: "None" },
],
},
CONFIG_DEFAULTS.toolChoice,
)
.field(
"parallelToolCalls",
"boolean",
{
displayName: "Parallel Tool Calls",
subtitle: "Allow the model to make parallel tool calls.",
},
CONFIG_DEFAULTS.parallelToolCalls,
)
/* ─── Request ─── */
.field(
"priority",
"select",
{
displayName: "Priority",
subtitle: "Request priority in the provider queue.",
options: [
{ value: "foreground", displayName: "Foreground" },
{ value: "normal", displayName: "Normal" },
{ value: "background", displayName: "Background" },
],
},
CONFIG_DEFAULTS.priority,
)
.field(
"timeout",
"numeric",
{
displayName: "Request Timeout (s)",
subtitle: "Max seconds a request may take (0 = no timeout).",
min: 0,
max: 600,
int: true,
},
CONFIG_DEFAULTS.timeout,
)
.field(
"maxRetries",
"numeric",
{
displayName: "Max Retries",
subtitle: "Retry attempts on 503 (0 to 5).",
min: 0,
max: 5,
int: true,
},
CONFIG_DEFAULTS.maxRetries,
)
/* ─── Diagnostics ─── */
.field(
"logLevel",
"select",
{
displayName: "Log Level",
subtitle: "Controls verbosity of diagnostic output in the developer console. Errors and warnings are always shown.",
options: [
{ value: "minimal", displayName: "Minimal" },
{ value: "normal", displayName: "Normal" },
{ value: "debug", displayName: "Debug" },
],
},
CONFIG_DEFAULTS.logLevel,
)
.field(
"showTurnSummaryInChat",
"boolean",
{
displayName: "Show Turn Summary in Chat",
subtitle: "Display the aggregated turn summary at the end of the response in the chat window.",
},
CONFIG_DEFAULTS.showTurnSummaryInChat,
)
.build();
/** Strongly-typed view of the resolved plugin configuration (derived from the schematics). */
export type ShartiConfig = InferParsedConfig<typeof configSchematics>;