@elizaos/plugin-lmstudio 2.0.3-beta.5 → 2.0.3-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.browser.js +849 -0
- package/dist/browser/index.browser.js.map +17 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.node.cjs +879 -0
- package/dist/cjs/index.node.cjs.map +17 -0
- package/dist/node/auto-enable.d.ts +3 -0
- package/dist/node/auto-enable.d.ts.map +1 -0
- package/dist/node/index.browser.d.ts +8 -0
- package/dist/node/index.browser.d.ts.map +1 -0
- package/dist/node/index.d.ts +2 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.node.d.ts +8 -0
- package/dist/node/index.node.d.ts.map +1 -0
- package/dist/node/index.node.js +849 -0
- package/dist/node/index.node.js.map +17 -0
- package/dist/node/models/embedding.d.ts +17 -0
- package/dist/node/models/embedding.d.ts.map +1 -0
- package/dist/node/models/index.d.ts +3 -0
- package/dist/node/models/index.d.ts.map +1 -0
- package/dist/node/models/text.d.ts +39 -0
- package/dist/node/models/text.d.ts.map +1 -0
- package/dist/node/plugin.d.ts +13 -0
- package/dist/node/plugin.d.ts.map +1 -0
- package/dist/node/types/index.d.ts +37 -0
- package/dist/node/types/index.d.ts.map +1 -0
- package/dist/node/utils/client.d.ts +17 -0
- package/dist/node/utils/client.d.ts.map +1 -0
- package/dist/node/utils/config.d.ts +37 -0
- package/dist/node/utils/config.d.ts.map +1 -0
- package/dist/node/utils/detect.d.ts +43 -0
- package/dist/node/utils/detect.d.ts.map +1 -0
- package/dist/node/utils/index.d.ts +4 -0
- package/dist/node/utils/index.d.ts.map +1 -0
- package/dist/node/utils/model-usage.d.ts +22 -0
- package/dist/node/utils/model-usage.d.ts.map +1 -0
- package/dist/node/vitest.config.d.ts +3 -0
- package/dist/node/vitest.config.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
// plugin.ts
|
|
2
|
+
import { logger as logger3, ModelType as ModelType3 } from "@elizaos/core";
|
|
3
|
+
|
|
4
|
+
// models/embedding.ts
|
|
5
|
+
import { logger, ModelType } from "@elizaos/core";
|
|
6
|
+
import { embed } from "ai";
|
|
7
|
+
|
|
8
|
+
// utils/client.ts
|
|
9
|
+
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
10
|
+
|
|
11
|
+
// utils/config.ts
|
|
12
|
+
var DEFAULT_LMSTUDIO_URL = "http://localhost:1234/v1";
|
|
13
|
+
function getEnvValue(key) {
|
|
14
|
+
if (typeof process === "undefined" || !process.env) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const value = process.env[key];
|
|
18
|
+
return value === undefined ? undefined : String(value);
|
|
19
|
+
}
|
|
20
|
+
function getSetting(runtime, key, defaultValue) {
|
|
21
|
+
const value = runtime.getSetting(key);
|
|
22
|
+
if (value !== undefined && value !== null) {
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
return getEnvValue(key) ?? defaultValue;
|
|
26
|
+
}
|
|
27
|
+
function getBaseURL(runtime) {
|
|
28
|
+
const raw = getSetting(runtime, "LMSTUDIO_BASE_URL") ?? DEFAULT_LMSTUDIO_URL;
|
|
29
|
+
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
30
|
+
if (trimmed === "") {
|
|
31
|
+
return DEFAULT_LMSTUDIO_URL;
|
|
32
|
+
}
|
|
33
|
+
if (/\/v\d+$/.test(trimmed)) {
|
|
34
|
+
return trimmed;
|
|
35
|
+
}
|
|
36
|
+
return `${trimmed}/v1`;
|
|
37
|
+
}
|
|
38
|
+
function getApiBase(runtime) {
|
|
39
|
+
const baseURL = getBaseURL(runtime);
|
|
40
|
+
return baseURL.replace(/\/v\d+$/, "");
|
|
41
|
+
}
|
|
42
|
+
function getApiKey(runtime) {
|
|
43
|
+
const value = getSetting(runtime, "LMSTUDIO_API_KEY");
|
|
44
|
+
if (!value || value.trim() === "") {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
return value.trim();
|
|
48
|
+
}
|
|
49
|
+
function getSmallModel(runtime) {
|
|
50
|
+
return getSetting(runtime, "LMSTUDIO_SMALL_MODEL") ?? getSetting(runtime, "SMALL_MODEL") ?? undefined;
|
|
51
|
+
}
|
|
52
|
+
function getLargeModel(runtime) {
|
|
53
|
+
return getSetting(runtime, "LMSTUDIO_LARGE_MODEL") ?? getSetting(runtime, "LARGE_MODEL") ?? undefined;
|
|
54
|
+
}
|
|
55
|
+
function getEmbeddingModel(runtime) {
|
|
56
|
+
return getSetting(runtime, "LMSTUDIO_EMBEDDING_MODEL") ?? undefined;
|
|
57
|
+
}
|
|
58
|
+
function shouldAutoDetect(runtime) {
|
|
59
|
+
const value = getSetting(runtime, "LMSTUDIO_AUTO_DETECT", "true")?.trim().toLowerCase();
|
|
60
|
+
if (value === undefined || value === "") {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// utils/client.ts
|
|
67
|
+
function createLMStudioClient(runtime) {
|
|
68
|
+
const baseURL = getBaseURL(runtime);
|
|
69
|
+
const apiKey = getApiKey(runtime);
|
|
70
|
+
return createOpenAICompatible({
|
|
71
|
+
name: "lmstudio",
|
|
72
|
+
baseURL,
|
|
73
|
+
...apiKey ? { apiKey } : {},
|
|
74
|
+
...runtime.fetch ? { fetch: runtime.fetch } : {},
|
|
75
|
+
includeUsage: true
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// utils/model-usage.ts
|
|
80
|
+
import { EventType } from "@elizaos/core";
|
|
81
|
+
function toFiniteNumber(value) {
|
|
82
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
return Math.max(0, Math.round(value));
|
|
86
|
+
}
|
|
87
|
+
function normalizeTokenUsage(usage) {
|
|
88
|
+
if (!usage || typeof usage !== "object") {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const record = usage;
|
|
92
|
+
const promptTokens = toFiniteNumber(record.inputTokens ?? record.promptTokens);
|
|
93
|
+
const completionTokens = toFiniteNumber(record.outputTokens ?? record.completionTokens);
|
|
94
|
+
const totalTokens = toFiniteNumber(record.totalTokens);
|
|
95
|
+
if (promptTokens === undefined && completionTokens === undefined && totalTokens === undefined) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const normalizedPromptTokens = promptTokens ?? (completionTokens === undefined && totalTokens !== undefined ? totalTokens : Math.max(0, (totalTokens ?? 0) - (completionTokens ?? 0)));
|
|
99
|
+
const normalizedCompletionTokens = completionTokens ?? Math.max(0, (totalTokens ?? normalizedPromptTokens) - normalizedPromptTokens);
|
|
100
|
+
return {
|
|
101
|
+
promptTokens: normalizedPromptTokens,
|
|
102
|
+
completionTokens: normalizedCompletionTokens,
|
|
103
|
+
totalTokens: totalTokens ?? normalizedPromptTokens + normalizedCompletionTokens
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function estimateTokenCount(text) {
|
|
107
|
+
return text.length === 0 ? 0 : Math.ceil(text.length / 4);
|
|
108
|
+
}
|
|
109
|
+
function stringifyForUsage(value) {
|
|
110
|
+
if (typeof value === "string") {
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
return JSON.stringify(value);
|
|
115
|
+
} catch {
|
|
116
|
+
return String(value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function estimateUsage(prompt, response) {
|
|
120
|
+
const promptTokens = estimateTokenCount(prompt);
|
|
121
|
+
const completionTokens = estimateTokenCount(stringifyForUsage(response));
|
|
122
|
+
return {
|
|
123
|
+
promptTokens,
|
|
124
|
+
completionTokens,
|
|
125
|
+
totalTokens: promptTokens + completionTokens,
|
|
126
|
+
estimated: true
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function estimateEmbeddingUsage(text) {
|
|
130
|
+
const promptTokens = estimateTokenCount(text);
|
|
131
|
+
return {
|
|
132
|
+
promptTokens,
|
|
133
|
+
completionTokens: 0,
|
|
134
|
+
totalTokens: promptTokens,
|
|
135
|
+
estimated: true
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function emitModelUsed(runtime, type, model, usage) {
|
|
139
|
+
runtime.emitEvent(EventType.MODEL_USED, {
|
|
140
|
+
runtime,
|
|
141
|
+
source: "lmstudio",
|
|
142
|
+
provider: "lmstudio",
|
|
143
|
+
type,
|
|
144
|
+
model,
|
|
145
|
+
modelName: model,
|
|
146
|
+
tokens: {
|
|
147
|
+
prompt: usage.promptTokens,
|
|
148
|
+
completion: usage.completionTokens,
|
|
149
|
+
total: usage.totalTokens,
|
|
150
|
+
...usage.estimated ? { estimated: true } : {}
|
|
151
|
+
},
|
|
152
|
+
...usage.estimated ? { usageEstimated: true } : {}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// models/embedding.ts
|
|
157
|
+
var DEFAULT_ZERO_VECTOR_DIM = 1536;
|
|
158
|
+
function extractText(params) {
|
|
159
|
+
if (params === null) {
|
|
160
|
+
return "";
|
|
161
|
+
}
|
|
162
|
+
if (typeof params === "string") {
|
|
163
|
+
return params;
|
|
164
|
+
}
|
|
165
|
+
if (typeof params === "object" && typeof params.text === "string") {
|
|
166
|
+
return params.text;
|
|
167
|
+
}
|
|
168
|
+
return "";
|
|
169
|
+
}
|
|
170
|
+
async function handleTextEmbedding(runtime, params) {
|
|
171
|
+
const modelName = getEmbeddingModel(runtime);
|
|
172
|
+
if (!modelName) {
|
|
173
|
+
logger.warn("[LMStudio] LMSTUDIO_EMBEDDING_MODEL not set — returning zero vector. Set it to a loaded embedding model in LM Studio.");
|
|
174
|
+
return new Array(DEFAULT_ZERO_VECTOR_DIM).fill(0);
|
|
175
|
+
}
|
|
176
|
+
let text = extractText(params);
|
|
177
|
+
const maxChars = 8000 * 4;
|
|
178
|
+
if (text.length > maxChars) {
|
|
179
|
+
logger.warn(`[LMStudio] Embedding input too long (~${Math.ceil(text.length / 4)} tokens), truncating to ~8000 tokens`);
|
|
180
|
+
text = text.slice(0, maxChars);
|
|
181
|
+
}
|
|
182
|
+
const embeddingText = text || "test";
|
|
183
|
+
try {
|
|
184
|
+
const client = createLMStudioClient(runtime);
|
|
185
|
+
const { embedding, usage } = await embed({
|
|
186
|
+
model: client.textEmbeddingModel(modelName),
|
|
187
|
+
value: embeddingText
|
|
188
|
+
});
|
|
189
|
+
emitModelUsed(runtime, ModelType.TEXT_EMBEDDING, modelName, normalizeTokenUsage(usage) ?? estimateEmbeddingUsage(embeddingText));
|
|
190
|
+
return embedding;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
logger.error({ error }, "[LMStudio] Error generating embedding");
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// models/text.ts
|
|
198
|
+
import {
|
|
199
|
+
buildCanonicalSystemPrompt,
|
|
200
|
+
dropDuplicateLeadingSystemMessage,
|
|
201
|
+
logger as logger2,
|
|
202
|
+
ModelType as ModelType2,
|
|
203
|
+
renderChatMessagesForPrompt,
|
|
204
|
+
resolveEffectiveSystemPrompt
|
|
205
|
+
} from "@elizaos/core";
|
|
206
|
+
import {
|
|
207
|
+
generateText,
|
|
208
|
+
jsonSchema,
|
|
209
|
+
Output,
|
|
210
|
+
streamText
|
|
211
|
+
} from "ai";
|
|
212
|
+
|
|
213
|
+
// utils/detect.ts
|
|
214
|
+
function normalizeBaseURL(input) {
|
|
215
|
+
const raw = (input ?? DEFAULT_LMSTUDIO_URL).replace(/\/+$/, "");
|
|
216
|
+
if (/\/v\d+$/.test(raw)) {
|
|
217
|
+
return raw;
|
|
218
|
+
}
|
|
219
|
+
return `${raw}/v1`;
|
|
220
|
+
}
|
|
221
|
+
function parseModelsResponse(body) {
|
|
222
|
+
if (Array.isArray(body)) {
|
|
223
|
+
return body.filter((entry) => {
|
|
224
|
+
return Boolean(entry) && typeof entry.id === "string";
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (body && typeof body === "object") {
|
|
228
|
+
const shaped = body;
|
|
229
|
+
if (Array.isArray(shaped.data)) {
|
|
230
|
+
return shaped.data.filter((entry) => {
|
|
231
|
+
return Boolean(entry) && typeof entry.id === "string";
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
async function detectLMStudio(options = {}) {
|
|
238
|
+
const baseURL = normalizeBaseURL(options.baseURL);
|
|
239
|
+
const fetcher = options.fetcher ?? fetch;
|
|
240
|
+
const timeoutMs = options.timeoutMs ?? 1500;
|
|
241
|
+
const controller = new AbortController;
|
|
242
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
243
|
+
try {
|
|
244
|
+
const headers = { "Content-Type": "application/json" };
|
|
245
|
+
if (options.apiKey) {
|
|
246
|
+
headers.Authorization = `Bearer ${options.apiKey}`;
|
|
247
|
+
}
|
|
248
|
+
const response = await fetcher(`${baseURL}/models`, {
|
|
249
|
+
method: "GET",
|
|
250
|
+
headers,
|
|
251
|
+
signal: controller.signal
|
|
252
|
+
});
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
return {
|
|
255
|
+
available: false,
|
|
256
|
+
baseURL,
|
|
257
|
+
error: `HTTP ${response.status} ${response.statusText}`
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const body = await response.json();
|
|
261
|
+
const models = parseModelsResponse(body);
|
|
262
|
+
if (!models) {
|
|
263
|
+
return {
|
|
264
|
+
available: false,
|
|
265
|
+
baseURL,
|
|
266
|
+
error: "unexpected /v1/models response shape"
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return { available: true, baseURL, models };
|
|
270
|
+
} catch (err) {
|
|
271
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
272
|
+
return { available: false, baseURL, error: message };
|
|
273
|
+
} finally {
|
|
274
|
+
clearTimeout(timer);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// models/text.ts
|
|
279
|
+
var TEXT_NANO_MODEL_TYPE = ModelType2.TEXT_NANO;
|
|
280
|
+
var TEXT_MEDIUM_MODEL_TYPE = ModelType2.TEXT_MEDIUM;
|
|
281
|
+
var TEXT_MEGA_MODEL_TYPE = ModelType2.TEXT_MEGA;
|
|
282
|
+
var RESPONSE_HANDLER_MODEL_TYPE = ModelType2.RESPONSE_HANDLER;
|
|
283
|
+
var ACTION_PLANNER_MODEL_TYPE = ModelType2.ACTION_PLANNER;
|
|
284
|
+
var _firstModelIdCache = new WeakMap;
|
|
285
|
+
async function resolveModelForType(runtime, modelType) {
|
|
286
|
+
if (modelType === ModelType2.TEXT_LARGE || modelType === TEXT_MEGA_MODEL_TYPE || modelType === ACTION_PLANNER_MODEL_TYPE) {
|
|
287
|
+
const large = getLargeModel(runtime);
|
|
288
|
+
if (large)
|
|
289
|
+
return large;
|
|
290
|
+
} else {
|
|
291
|
+
const small = getSmallModel(runtime);
|
|
292
|
+
if (small)
|
|
293
|
+
return small;
|
|
294
|
+
}
|
|
295
|
+
let pending = _firstModelIdCache.get(runtime);
|
|
296
|
+
if (!pending) {
|
|
297
|
+
pending = (async () => {
|
|
298
|
+
const result = await detectLMStudio({
|
|
299
|
+
baseURL: getBaseURL(runtime),
|
|
300
|
+
...runtime.fetch ? { fetcher: runtime.fetch } : {}
|
|
301
|
+
});
|
|
302
|
+
if (!result.available || !result.models || result.models.length === 0) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
const first = result.models[0];
|
|
306
|
+
return first.id;
|
|
307
|
+
})();
|
|
308
|
+
_firstModelIdCache.set(runtime, pending);
|
|
309
|
+
}
|
|
310
|
+
const resolved = await pending;
|
|
311
|
+
if (resolved) {
|
|
312
|
+
return resolved;
|
|
313
|
+
}
|
|
314
|
+
throw new Error("[LMStudio] No model configured and `GET /v1/models` returned no entries. Set LMSTUDIO_SMALL_MODEL / LMSTUDIO_LARGE_MODEL or load a model in LM Studio.");
|
|
315
|
+
}
|
|
316
|
+
function summarizeAiSdkError(error, depth = 0) {
|
|
317
|
+
if (depth > 4) {
|
|
318
|
+
return { note: "max depth summarizing nested error" };
|
|
319
|
+
}
|
|
320
|
+
if (error == null) {
|
|
321
|
+
return { raw: String(error) };
|
|
322
|
+
}
|
|
323
|
+
if (typeof error !== "object") {
|
|
324
|
+
return { message: String(error) };
|
|
325
|
+
}
|
|
326
|
+
const e = error;
|
|
327
|
+
const out = {};
|
|
328
|
+
if (typeof e.name === "string")
|
|
329
|
+
out.errorName = e.name;
|
|
330
|
+
if (typeof e.message === "string")
|
|
331
|
+
out.message = e.message;
|
|
332
|
+
if (typeof e.url === "string")
|
|
333
|
+
out.requestUrl = e.url;
|
|
334
|
+
if (typeof e.statusCode === "number")
|
|
335
|
+
out.httpStatus = e.statusCode;
|
|
336
|
+
if (typeof e.responseBody === "string")
|
|
337
|
+
out.lmstudioResponseBody = e.responseBody;
|
|
338
|
+
if (e.cause != null && typeof e.cause === "object") {
|
|
339
|
+
out.cause = summarizeAiSdkError(e.cause, depth + 1);
|
|
340
|
+
}
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
function logTextFailure(phase, modelType, modelId, endpoint, error) {
|
|
344
|
+
logger2.error({
|
|
345
|
+
src: "plugin:lmstudio:text",
|
|
346
|
+
phase,
|
|
347
|
+
modelType,
|
|
348
|
+
modelId,
|
|
349
|
+
lmstudioBaseURL: endpoint,
|
|
350
|
+
...summarizeAiSdkError(error)
|
|
351
|
+
}, `[LMStudio] ${phase} failed (${modelType}, model=${modelId}).`);
|
|
352
|
+
}
|
|
353
|
+
function buildStructuredOutput(responseSchema) {
|
|
354
|
+
if (responseSchema && typeof responseSchema === "object" && "responseFormat" in responseSchema && "parseCompleteOutput" in responseSchema) {
|
|
355
|
+
return responseSchema;
|
|
356
|
+
}
|
|
357
|
+
const schemaOptions = responseSchema && typeof responseSchema === "object" && "schema" in responseSchema ? responseSchema : { schema: responseSchema };
|
|
358
|
+
return Output.object({
|
|
359
|
+
schema: jsonSchema(schemaOptions.schema),
|
|
360
|
+
...schemaOptions.name ? { name: schemaOptions.name } : {},
|
|
361
|
+
...schemaOptions.description ? { description: schemaOptions.description } : {}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function serializeStructuredResult(result) {
|
|
365
|
+
if (result.output !== undefined && result.output !== null) {
|
|
366
|
+
return typeof result.output === "string" ? result.output : JSON.stringify(result.output);
|
|
367
|
+
}
|
|
368
|
+
const trimmed = result.text.trim();
|
|
369
|
+
if (trimmed)
|
|
370
|
+
return trimmed;
|
|
371
|
+
throw new Error("[LMStudio] Structured generation returned no text or output.");
|
|
372
|
+
}
|
|
373
|
+
function asRecord(value) {
|
|
374
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
375
|
+
}
|
|
376
|
+
function firstString(...values) {
|
|
377
|
+
for (const value of values) {
|
|
378
|
+
if (typeof value === "string" && value.length > 0) {
|
|
379
|
+
return value;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
function parseJsonIfPossible(value) {
|
|
385
|
+
if (typeof value !== "string") {
|
|
386
|
+
return value;
|
|
387
|
+
}
|
|
388
|
+
try {
|
|
389
|
+
return JSON.parse(value);
|
|
390
|
+
} catch {
|
|
391
|
+
return value;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function inferJsonSchemaType(schema, isRoot) {
|
|
395
|
+
if ("items" in schema && !("properties" in schema)) {
|
|
396
|
+
return "array";
|
|
397
|
+
}
|
|
398
|
+
if ("properties" in schema || "required" in schema || "additionalProperties" in schema || isRoot) {
|
|
399
|
+
return "object";
|
|
400
|
+
}
|
|
401
|
+
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
402
|
+
const types = new Set(schema.enum.map((value) => typeof value));
|
|
403
|
+
if (types.size === 1) {
|
|
404
|
+
const [type] = [...types];
|
|
405
|
+
if (type === "string" || type === "number" || type === "boolean") {
|
|
406
|
+
return type;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
function sanitizeJsonSchema(schema, isRoot = false) {
|
|
413
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
414
|
+
return { type: "object" };
|
|
415
|
+
}
|
|
416
|
+
const record = schema;
|
|
417
|
+
const sanitized = { ...record };
|
|
418
|
+
if (typeof sanitized.type !== "string") {
|
|
419
|
+
const inferredType = inferJsonSchemaType(sanitized, isRoot);
|
|
420
|
+
if (inferredType) {
|
|
421
|
+
sanitized.type = inferredType;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (sanitized.properties && typeof sanitized.properties === "object" && !Array.isArray(sanitized.properties)) {
|
|
425
|
+
const properties = {};
|
|
426
|
+
for (const [key, value] of Object.entries(sanitized.properties)) {
|
|
427
|
+
properties[key] = sanitizeJsonSchema(value);
|
|
428
|
+
}
|
|
429
|
+
sanitized.properties = properties;
|
|
430
|
+
}
|
|
431
|
+
if (sanitized.items) {
|
|
432
|
+
sanitized.items = Array.isArray(sanitized.items) ? sanitized.items.map((item) => sanitizeJsonSchema(item)) : sanitizeJsonSchema(sanitized.items);
|
|
433
|
+
}
|
|
434
|
+
for (const unionKey of ["anyOf", "oneOf", "allOf"]) {
|
|
435
|
+
const value = sanitized[unionKey];
|
|
436
|
+
if (Array.isArray(value)) {
|
|
437
|
+
sanitized[unionKey] = value.map((item) => sanitizeJsonSchema(item));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return sanitized;
|
|
441
|
+
}
|
|
442
|
+
function normalizeNativeTools(tools) {
|
|
443
|
+
if (!tools) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (!Array.isArray(tools)) {
|
|
447
|
+
return tools;
|
|
448
|
+
}
|
|
449
|
+
const toolSet = {};
|
|
450
|
+
for (const rawTool of tools) {
|
|
451
|
+
const tool = asRecord(rawTool);
|
|
452
|
+
const functionTool = asRecord(tool.function);
|
|
453
|
+
const name = firstString(tool.name, functionTool.name);
|
|
454
|
+
if (!name) {
|
|
455
|
+
throw new Error("[LMStudio] Native tool definition is missing a name.");
|
|
456
|
+
}
|
|
457
|
+
const description = firstString(tool.description, functionTool.description);
|
|
458
|
+
const rawSchema = tool.parameters ?? functionTool.parameters ?? { type: "object" };
|
|
459
|
+
const inputSchema = sanitizeJsonSchema(rawSchema, true);
|
|
460
|
+
toolSet[name] = {
|
|
461
|
+
...description ? { description } : {},
|
|
462
|
+
inputSchema: jsonSchema(inputSchema)
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
return Object.keys(toolSet).length > 0 ? toolSet : undefined;
|
|
466
|
+
}
|
|
467
|
+
function normalizeToolChoice(toolChoice) {
|
|
468
|
+
if (!toolChoice) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (typeof toolChoice === "string" && (toolChoice === "auto" || toolChoice === "none" || toolChoice === "required")) {
|
|
472
|
+
return toolChoice;
|
|
473
|
+
}
|
|
474
|
+
const choice = asRecord(toolChoice);
|
|
475
|
+
if (choice.type === "tool") {
|
|
476
|
+
const toolName = firstString(choice.toolName, choice.name);
|
|
477
|
+
if (toolName) {
|
|
478
|
+
return { type: "tool", toolName };
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (choice.type === "function") {
|
|
482
|
+
const fn = asRecord(choice.function);
|
|
483
|
+
const toolName = firstString(fn.name);
|
|
484
|
+
if (toolName) {
|
|
485
|
+
return { type: "tool", toolName };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return toolChoice;
|
|
489
|
+
}
|
|
490
|
+
function stringifyMessageContent(content) {
|
|
491
|
+
if (typeof content === "string")
|
|
492
|
+
return content;
|
|
493
|
+
if (content == null)
|
|
494
|
+
return "";
|
|
495
|
+
if (typeof content === "object") {
|
|
496
|
+
try {
|
|
497
|
+
return JSON.stringify(content);
|
|
498
|
+
} catch {
|
|
499
|
+
return "[unserializable content]";
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return String(content);
|
|
503
|
+
}
|
|
504
|
+
function normalizeUserContent(content) {
|
|
505
|
+
if (Array.isArray(content)) {
|
|
506
|
+
return content;
|
|
507
|
+
}
|
|
508
|
+
return stringifyMessageContent(content);
|
|
509
|
+
}
|
|
510
|
+
function normalizeNativeMessage(message) {
|
|
511
|
+
const raw = asRecord(message);
|
|
512
|
+
if (raw.role === "system") {
|
|
513
|
+
return {
|
|
514
|
+
role: "system",
|
|
515
|
+
content: stringifyMessageContent(raw.content)
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
if (raw.role === "assistant") {
|
|
519
|
+
return {
|
|
520
|
+
role: "assistant",
|
|
521
|
+
content: typeof raw.content === "string" || Array.isArray(raw.content) ? raw.content : ""
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (raw.role === "tool") {
|
|
525
|
+
return {
|
|
526
|
+
role: "tool",
|
|
527
|
+
content: Array.isArray(raw.content) ? raw.content : [
|
|
528
|
+
{
|
|
529
|
+
type: "tool-result",
|
|
530
|
+
toolCallId: String(firstString(raw.toolCallId, raw.id) ?? "tool-call"),
|
|
531
|
+
toolName: String(firstString(raw.toolName, raw.name) ?? "tool"),
|
|
532
|
+
output: {
|
|
533
|
+
type: "text",
|
|
534
|
+
value: stringifyMessageContent(raw.content)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
]
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
role: "user",
|
|
542
|
+
content: normalizeUserContent(raw.content)
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function normalizeNativeMessages(messages) {
|
|
546
|
+
if (!Array.isArray(messages)) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
return messages.map((m) => normalizeNativeMessage(m));
|
|
550
|
+
}
|
|
551
|
+
function mapToolCalls(toolCalls) {
|
|
552
|
+
if (!Array.isArray(toolCalls) || toolCalls.length === 0) {
|
|
553
|
+
return [];
|
|
554
|
+
}
|
|
555
|
+
const out = [];
|
|
556
|
+
for (const raw of toolCalls) {
|
|
557
|
+
const r = asRecord(raw);
|
|
558
|
+
const id = String(firstString(r.toolCallId, r.id) ?? "");
|
|
559
|
+
const name = String(firstString(r.toolName, r.name) ?? "").trim();
|
|
560
|
+
if (!name)
|
|
561
|
+
continue;
|
|
562
|
+
const rawInput = r.input ?? r.arguments ?? r.args;
|
|
563
|
+
let args;
|
|
564
|
+
if (typeof rawInput === "string") {
|
|
565
|
+
const parsed = parseJsonIfPossible(rawInput);
|
|
566
|
+
args = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : rawInput;
|
|
567
|
+
} else if (rawInput && typeof rawInput === "object" && !Array.isArray(rawInput)) {
|
|
568
|
+
args = rawInput;
|
|
569
|
+
} else {
|
|
570
|
+
args = {};
|
|
571
|
+
}
|
|
572
|
+
out.push({ id, name, arguments: args });
|
|
573
|
+
}
|
|
574
|
+
return out;
|
|
575
|
+
}
|
|
576
|
+
function buildNativeResultCast(result, modelName, usage) {
|
|
577
|
+
const payload = {
|
|
578
|
+
text: result.text,
|
|
579
|
+
toolCalls: mapToolCalls(result.toolCalls),
|
|
580
|
+
finishReason: String(result.finishReason),
|
|
581
|
+
usage,
|
|
582
|
+
providerMetadata: { modelName }
|
|
583
|
+
};
|
|
584
|
+
return payload;
|
|
585
|
+
}
|
|
586
|
+
function buildStreamResult(args) {
|
|
587
|
+
const streamResult = streamText(args.streamParams);
|
|
588
|
+
const textPromise = Promise.resolve(streamResult.text).catch(() => "");
|
|
589
|
+
const finishReasonPromise = Promise.resolve(streamResult.finishReason).catch(() => {
|
|
590
|
+
return;
|
|
591
|
+
});
|
|
592
|
+
const usagePromise = Promise.resolve(streamResult.usage).then(async (usage) => {
|
|
593
|
+
const fullText = await textPromise;
|
|
594
|
+
const normalized = normalizeTokenUsage(usage) ?? estimateUsage(args.promptForEstimate, fullText);
|
|
595
|
+
emitModelUsed(args.runtime, args.modelType, args.model, normalized);
|
|
596
|
+
return normalized;
|
|
597
|
+
}).catch(() => {
|
|
598
|
+
return;
|
|
599
|
+
});
|
|
600
|
+
async function* textStreamWithUsage() {
|
|
601
|
+
let completed = false;
|
|
602
|
+
try {
|
|
603
|
+
for await (const chunk of streamResult.textStream) {
|
|
604
|
+
yield chunk;
|
|
605
|
+
}
|
|
606
|
+
completed = true;
|
|
607
|
+
} catch (err) {
|
|
608
|
+
logTextFailure("streamText.textStream", args.modelType, args.model, args.endpoint, err);
|
|
609
|
+
throw err;
|
|
610
|
+
} finally {
|
|
611
|
+
if (completed) {
|
|
612
|
+
await usagePromise.catch(() => {
|
|
613
|
+
return;
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
textStream: textStreamWithUsage(),
|
|
620
|
+
text: textPromise,
|
|
621
|
+
usage: usagePromise,
|
|
622
|
+
finishReason: finishReasonPromise
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
async function handleTextWithModelType(runtime, modelType, params) {
|
|
626
|
+
const extended = params;
|
|
627
|
+
const responseSchema = extended.responseSchema;
|
|
628
|
+
const tools = normalizeNativeTools(extended.tools);
|
|
629
|
+
const {
|
|
630
|
+
prompt,
|
|
631
|
+
maxTokens = 8192,
|
|
632
|
+
temperature = 0.7,
|
|
633
|
+
frequencyPenalty = 0.7,
|
|
634
|
+
presencePenalty = 0.7
|
|
635
|
+
} = params;
|
|
636
|
+
let modelIdForLog = "";
|
|
637
|
+
const baseURL = getBaseURL(runtime);
|
|
638
|
+
try {
|
|
639
|
+
const client = createLMStudioClient(runtime);
|
|
640
|
+
const model = await resolveModelForType(runtime, modelType);
|
|
641
|
+
modelIdForLog = model;
|
|
642
|
+
logger2.log(`[LMStudio] Using ${modelType} model: ${model}`);
|
|
643
|
+
const system = resolveEffectiveSystemPrompt({
|
|
644
|
+
params,
|
|
645
|
+
fallback: buildCanonicalSystemPrompt({ character: runtime.character })
|
|
646
|
+
});
|
|
647
|
+
let outputSpec = responseSchema !== undefined && responseSchema !== null ? buildStructuredOutput(responseSchema) : undefined;
|
|
648
|
+
if (tools && outputSpec) {
|
|
649
|
+
logger2.debug("[LMStudio] tools and responseSchema both present — omitting structured output for this call.");
|
|
650
|
+
outputSpec = undefined;
|
|
651
|
+
}
|
|
652
|
+
const wireRaw = dropDuplicateLeadingSystemMessage(extended.messages, system);
|
|
653
|
+
const normalizedMessages = normalizeNativeMessages(wireRaw);
|
|
654
|
+
const hasChatMessages = Array.isArray(normalizedMessages) && normalizedMessages.length > 0;
|
|
655
|
+
const toolChoice = tools ? normalizeToolChoice(extended.toolChoice) : undefined;
|
|
656
|
+
const shouldReturnNative = Boolean(hasChatMessages || tools || extended.toolChoice || outputSpec !== undefined);
|
|
657
|
+
const renderedPrompt = hasChatMessages ? "" : renderChatMessagesForPrompt(params.messages, {
|
|
658
|
+
...system ? { omitDuplicateSystem: system } : {}
|
|
659
|
+
}) ?? prompt ?? "";
|
|
660
|
+
const promptOrMessages = hasChatMessages ? { messages: normalizedMessages } : { prompt: renderedPrompt };
|
|
661
|
+
const resolvedStopSequences = Array.isArray(params.stopSequences) && params.stopSequences.length > 0 ? params.stopSequences : undefined;
|
|
662
|
+
const promptForUsageEstimate = hasChatMessages ? JSON.stringify(normalizedMessages) : renderedPrompt;
|
|
663
|
+
const baseArgs = {
|
|
664
|
+
model: client(model),
|
|
665
|
+
...promptOrMessages,
|
|
666
|
+
...system ? { system } : {},
|
|
667
|
+
temperature,
|
|
668
|
+
maxOutputTokens: maxTokens,
|
|
669
|
+
frequencyPenalty,
|
|
670
|
+
presencePenalty,
|
|
671
|
+
...resolvedStopSequences ? { stopSequences: resolvedStopSequences } : {},
|
|
672
|
+
...tools ? { tools, ...toolChoice ? { toolChoice } : {} } : {},
|
|
673
|
+
...outputSpec ? { output: outputSpec } : {}
|
|
674
|
+
};
|
|
675
|
+
if (params.stream && !outputSpec && !(extended.toolChoice && !tools)) {
|
|
676
|
+
return buildStreamResult({
|
|
677
|
+
runtime,
|
|
678
|
+
modelType,
|
|
679
|
+
model,
|
|
680
|
+
endpoint: baseURL,
|
|
681
|
+
streamParams: baseArgs,
|
|
682
|
+
promptForEstimate: promptForUsageEstimate
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
const result = await generateText(baseArgs);
|
|
686
|
+
const usage = normalizeTokenUsage(result.usage) ?? estimateUsage(promptForUsageEstimate, result.text);
|
|
687
|
+
emitModelUsed(runtime, modelType, model, usage);
|
|
688
|
+
if (shouldReturnNative) {
|
|
689
|
+
if (outputSpec !== undefined) {
|
|
690
|
+
return serializeStructuredResult(result);
|
|
691
|
+
}
|
|
692
|
+
return buildNativeResultCast(result, model, usage);
|
|
693
|
+
}
|
|
694
|
+
return result.text;
|
|
695
|
+
} catch (error) {
|
|
696
|
+
logTextFailure("generateText", modelType, modelIdForLog || "(unknown)", baseURL, error);
|
|
697
|
+
throw error;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
async function handleTextSmall(runtime, params) {
|
|
701
|
+
return handleTextWithModelType(runtime, ModelType2.TEXT_SMALL, params);
|
|
702
|
+
}
|
|
703
|
+
async function handleTextNano(runtime, params) {
|
|
704
|
+
return handleTextWithModelType(runtime, TEXT_NANO_MODEL_TYPE, params);
|
|
705
|
+
}
|
|
706
|
+
async function handleTextMedium(runtime, params) {
|
|
707
|
+
return handleTextWithModelType(runtime, TEXT_MEDIUM_MODEL_TYPE, params);
|
|
708
|
+
}
|
|
709
|
+
async function handleTextLarge(runtime, params) {
|
|
710
|
+
return handleTextWithModelType(runtime, ModelType2.TEXT_LARGE, params);
|
|
711
|
+
}
|
|
712
|
+
async function handleTextMega(runtime, params) {
|
|
713
|
+
return handleTextWithModelType(runtime, TEXT_MEGA_MODEL_TYPE, params);
|
|
714
|
+
}
|
|
715
|
+
async function handleResponseHandler(runtime, params) {
|
|
716
|
+
return handleTextWithModelType(runtime, RESPONSE_HANDLER_MODEL_TYPE, params);
|
|
717
|
+
}
|
|
718
|
+
async function handleActionPlanner(runtime, params) {
|
|
719
|
+
return handleTextWithModelType(runtime, ACTION_PLANNER_MODEL_TYPE, params);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// plugin.ts
|
|
723
|
+
function getProcessEnv() {
|
|
724
|
+
if (typeof process === "undefined" || !process.env) {
|
|
725
|
+
return {};
|
|
726
|
+
}
|
|
727
|
+
return process.env;
|
|
728
|
+
}
|
|
729
|
+
var env = getProcessEnv();
|
|
730
|
+
var TEXT_NANO_MODEL_TYPE2 = ModelType3.TEXT_NANO;
|
|
731
|
+
var TEXT_MEDIUM_MODEL_TYPE2 = ModelType3.TEXT_MEDIUM;
|
|
732
|
+
var TEXT_MEGA_MODEL_TYPE2 = ModelType3.TEXT_MEGA;
|
|
733
|
+
var RESPONSE_HANDLER_MODEL_TYPE2 = ModelType3.RESPONSE_HANDLER;
|
|
734
|
+
var ACTION_PLANNER_MODEL_TYPE2 = ModelType3.ACTION_PLANNER;
|
|
735
|
+
var lmStudioPlugin = {
|
|
736
|
+
name: "lmstudio",
|
|
737
|
+
description: "LM Studio provider for local LLM inference via the OpenAI-compatible API",
|
|
738
|
+
autoEnable: {
|
|
739
|
+
envKeys: ["LMSTUDIO_BASE_URL"],
|
|
740
|
+
shouldEnable: async () => {
|
|
741
|
+
try {
|
|
742
|
+
const result = await detectLMStudio({ timeoutMs: 750 });
|
|
743
|
+
return result.available;
|
|
744
|
+
} catch {
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
config: {
|
|
750
|
+
LMSTUDIO_BASE_URL: env.LMSTUDIO_BASE_URL ?? null,
|
|
751
|
+
LMSTUDIO_API_KEY: env.LMSTUDIO_API_KEY ?? null,
|
|
752
|
+
LMSTUDIO_SMALL_MODEL: env.LMSTUDIO_SMALL_MODEL ?? null,
|
|
753
|
+
LMSTUDIO_LARGE_MODEL: env.LMSTUDIO_LARGE_MODEL ?? null,
|
|
754
|
+
LMSTUDIO_EMBEDDING_MODEL: env.LMSTUDIO_EMBEDDING_MODEL ?? null,
|
|
755
|
+
LMSTUDIO_AUTO_DETECT: env.LMSTUDIO_AUTO_DETECT ?? null,
|
|
756
|
+
SMALL_MODEL: env.SMALL_MODEL ?? null,
|
|
757
|
+
LARGE_MODEL: env.LARGE_MODEL ?? null
|
|
758
|
+
},
|
|
759
|
+
async init(_config, runtime) {
|
|
760
|
+
const baseURL = getBaseURL(runtime);
|
|
761
|
+
if (!shouldAutoDetect(runtime)) {
|
|
762
|
+
logger3.debug("[LMStudio] LMSTUDIO_AUTO_DETECT disabled — skipping init probe.");
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const apiKey = getApiKey(runtime);
|
|
766
|
+
const result = await detectLMStudio({
|
|
767
|
+
baseURL,
|
|
768
|
+
...apiKey ? { apiKey } : {},
|
|
769
|
+
...runtime.fetch ? { fetcher: runtime.fetch } : {},
|
|
770
|
+
timeoutMs: 2000
|
|
771
|
+
});
|
|
772
|
+
if (!result.available) {
|
|
773
|
+
logger3.warn({ src: "plugin:lmstudio", baseURL, error: result.error }, "[LMStudio] /v1/models probe failed — plugin will only succeed once LM Studio is running.");
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const modelCount = result.models?.length ?? 0;
|
|
777
|
+
logger3.info(`[LMStudio] Detected ${modelCount} model${modelCount === 1 ? "" : "s"} at ${baseURL}`);
|
|
778
|
+
},
|
|
779
|
+
models: {
|
|
780
|
+
[ModelType3.TEXT_EMBEDDING]: async (runtime, params) => {
|
|
781
|
+
return handleTextEmbedding(runtime, params);
|
|
782
|
+
},
|
|
783
|
+
[TEXT_NANO_MODEL_TYPE2]: async (runtime, params) => {
|
|
784
|
+
return handleTextNano(runtime, params);
|
|
785
|
+
},
|
|
786
|
+
[ModelType3.TEXT_SMALL]: async (runtime, params) => {
|
|
787
|
+
return handleTextSmall(runtime, params);
|
|
788
|
+
},
|
|
789
|
+
[TEXT_MEDIUM_MODEL_TYPE2]: async (runtime, params) => {
|
|
790
|
+
return handleTextMedium(runtime, params);
|
|
791
|
+
},
|
|
792
|
+
[ModelType3.TEXT_LARGE]: async (runtime, params) => {
|
|
793
|
+
return handleTextLarge(runtime, params);
|
|
794
|
+
},
|
|
795
|
+
[TEXT_MEGA_MODEL_TYPE2]: async (runtime, params) => {
|
|
796
|
+
return handleTextMega(runtime, params);
|
|
797
|
+
},
|
|
798
|
+
[RESPONSE_HANDLER_MODEL_TYPE2]: async (runtime, params) => {
|
|
799
|
+
return handleResponseHandler(runtime, params);
|
|
800
|
+
},
|
|
801
|
+
[ACTION_PLANNER_MODEL_TYPE2]: async (runtime, params) => {
|
|
802
|
+
return handleActionPlanner(runtime, params);
|
|
803
|
+
}
|
|
804
|
+
},
|
|
805
|
+
tests: [
|
|
806
|
+
{
|
|
807
|
+
name: "lmstudio_plugin_tests",
|
|
808
|
+
tests: [
|
|
809
|
+
{
|
|
810
|
+
name: "lmstudio_test_models_endpoint",
|
|
811
|
+
fn: async (runtime) => {
|
|
812
|
+
const apiKey = getApiKey(runtime);
|
|
813
|
+
const result = await detectLMStudio({
|
|
814
|
+
baseURL: getBaseURL(runtime),
|
|
815
|
+
...apiKey ? { apiKey } : {},
|
|
816
|
+
...runtime.fetch ? { fetcher: runtime.fetch } : {}
|
|
817
|
+
});
|
|
818
|
+
if (!result.available) {
|
|
819
|
+
logger3.error({ result }, "[LMStudio] /v1/models probe failed");
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
logger3.log({ models: result.models?.length ?? 0 }, "[LMStudio] /v1/models OK");
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
}
|
|
827
|
+
]
|
|
828
|
+
};
|
|
829
|
+
// index.browser.ts
|
|
830
|
+
var defaultLMStudioPlugin = lmStudioPlugin;
|
|
831
|
+
var index_browser_default = defaultLMStudioPlugin;
|
|
832
|
+
export {
|
|
833
|
+
shouldAutoDetect,
|
|
834
|
+
parseModelsResponse,
|
|
835
|
+
lmStudioPlugin,
|
|
836
|
+
getSmallModel,
|
|
837
|
+
getSetting,
|
|
838
|
+
getLargeModel,
|
|
839
|
+
getEmbeddingModel,
|
|
840
|
+
getBaseURL,
|
|
841
|
+
getApiKey,
|
|
842
|
+
getApiBase,
|
|
843
|
+
detectLMStudio,
|
|
844
|
+
index_browser_default as default,
|
|
845
|
+
DEFAULT_LMSTUDIO_URL
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
//# debugId=1609C405BA70E08F64756E2164756E21
|
|
849
|
+
//# sourceMappingURL=index.browser.js.map
|