@goondocks/myco 0.4.0 → 0.4.2
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +4 -5
- package/README.md +1 -1
- package/dist/{chunk-P7RNAYU7.js → chunk-67R6EMYD.js} +61 -9
- package/dist/chunk-67R6EMYD.js.map +1 -0
- package/dist/{chunk-G6ZMTQMJ.js → chunk-6UJWI4IW.js} +3 -1
- package/dist/{chunk-G6ZMTQMJ.js.map → chunk-6UJWI4IW.js.map} +1 -1
- package/dist/{chunk-S7EIHYE7.js → chunk-FPEDTLQ6.js} +3 -3
- package/dist/{chunk-S7EIHYE7.js.map → chunk-FPEDTLQ6.js.map} +1 -1
- package/dist/{chunk-XHWIIU5D.js → chunk-GFBG73P4.js} +2 -2
- package/dist/{chunk-TZDDXRHG.js → chunk-I7PNZEBO.js} +2 -2
- package/dist/{chunk-IVS5MYBL.js → chunk-IYFKPSRP.js} +2 -2
- package/dist/{chunk-NUA7UTIY.js → chunk-MIU3DKLN.js} +2 -2
- package/dist/{chunk-VYV5IFD6.js → chunk-T7OC6GH5.js} +2 -2
- package/dist/chunk-TBRZAJ7W.js +135 -0
- package/dist/chunk-TBRZAJ7W.js.map +1 -0
- package/dist/{chunk-4FCFRJIQ.js → chunk-UKWO26VI.js} +2 -2
- package/dist/{chunk-YZO22BBI.js → chunk-V2OWD2VV.js} +4 -4
- package/dist/{chunk-RDXTQ436.js → chunk-WBT5DWGC.js} +2 -2
- package/dist/{cli-ZN6VBA7V.js → cli-PMOFCZQL.js} +15 -15
- package/dist/{config-4GGMWGAF.js → config-5FGLQGCW.js} +3 -3
- package/dist/{detect-providers-5FU3BN5Q.js → detect-providers-IRL2TTLK.js} +2 -2
- package/dist/{init-7UXGDOFS.js → init-NUF5UBUJ.js} +6 -6
- package/dist/{main-6UPAIDGS.js → main-2XEBVUR6.js} +19 -10
- package/dist/{main-6UPAIDGS.js.map → main-2XEBVUR6.js.map} +1 -1
- package/dist/{rebuild-QDSYYCS7.js → rebuild-E6YFIRYZ.js} +6 -6
- package/dist/{reprocess-ZNUQCIS3.js → reprocess-7G7KQWCN.js} +9 -9
- package/dist/{restart-5UY2KV54.js → restart-ABW4ZK3P.js} +3 -3
- package/dist/{search-2VEN3XIG.js → search-MPD7SFK6.js} +5 -5
- package/dist/{server-OR5B4B7K.js → server-NZLZRITH.js} +9 -9
- package/dist/{session-start-TUITIUMB.js → session-start-YB4A4PZB.js} +4 -4
- package/dist/{setup-digest-ETCZAUIU.js → setup-digest-K732MGOJ.js} +5 -5
- package/dist/{setup-llm-DWEJE3JE.js → setup-llm-XCCH5LYD.js} +5 -5
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +2 -2
- package/dist/src/mcp/server.js +1 -1
- package/dist/{stats-IVIXIKTS.js → stats-6G7SN5YZ.js} +3 -3
- package/dist/{verify-4H6CEE5T.js → verify-JFHQH55Z.js} +5 -5
- package/package.json +1 -1
- package/skills/myco/SKILL.md +5 -1
- package/skills/myco/references/cli-usage.md +322 -0
- package/skills/myco/references/vault-status.md +224 -0
- package/skills/setup/SKILL.md +146 -0
- package/skills/setup/references/model-recommendations.md +77 -0
- package/commands/init.md +0 -122
- package/commands/setup-llm.md +0 -114
- package/commands/status.md +0 -130
- package/dist/chunk-P7RNAYU7.js.map +0 -1
- package/dist/chunk-QQ36XEJP.js +0 -38
- package/dist/chunk-QQ36XEJP.js.map +0 -1
- /package/dist/{chunk-XHWIIU5D.js.map → chunk-GFBG73P4.js.map} +0 -0
- /package/dist/{chunk-TZDDXRHG.js.map → chunk-I7PNZEBO.js.map} +0 -0
- /package/dist/{chunk-IVS5MYBL.js.map → chunk-IYFKPSRP.js.map} +0 -0
- /package/dist/{chunk-NUA7UTIY.js.map → chunk-MIU3DKLN.js.map} +0 -0
- /package/dist/{chunk-VYV5IFD6.js.map → chunk-T7OC6GH5.js.map} +0 -0
- /package/dist/{chunk-4FCFRJIQ.js.map → chunk-UKWO26VI.js.map} +0 -0
- /package/dist/{chunk-YZO22BBI.js.map → chunk-V2OWD2VV.js.map} +0 -0
- /package/dist/{chunk-RDXTQ436.js.map → chunk-WBT5DWGC.js.map} +0 -0
- /package/dist/{cli-ZN6VBA7V.js.map → cli-PMOFCZQL.js.map} +0 -0
- /package/dist/{config-4GGMWGAF.js.map → config-5FGLQGCW.js.map} +0 -0
- /package/dist/{detect-providers-5FU3BN5Q.js.map → detect-providers-IRL2TTLK.js.map} +0 -0
- /package/dist/{init-7UXGDOFS.js.map → init-NUF5UBUJ.js.map} +0 -0
- /package/dist/{rebuild-QDSYYCS7.js.map → rebuild-E6YFIRYZ.js.map} +0 -0
- /package/dist/{reprocess-ZNUQCIS3.js.map → reprocess-7G7KQWCN.js.map} +0 -0
- /package/dist/{restart-5UY2KV54.js.map → restart-ABW4ZK3P.js.map} +0 -0
- /package/dist/{search-2VEN3XIG.js.map → search-MPD7SFK6.js.map} +0 -0
- /package/dist/{server-OR5B4B7K.js.map → server-NZLZRITH.js.map} +0 -0
- /package/dist/{session-start-TUITIUMB.js.map → session-start-YB4A4PZB.js.map} +0 -0
- /package/dist/{setup-digest-ETCZAUIU.js.map → setup-digest-K732MGOJ.js.map} +0 -0
- /package/dist/{setup-llm-DWEJE3JE.js.map → setup-llm-XCCH5LYD.js.map} +0 -0
- /package/dist/{stats-IVIXIKTS.js.map → stats-6G7SN5YZ.js.map} +0 -0
- /package/dist/{verify-4H6CEE5T.js.map → verify-JFHQH55Z.js.map} +0 -0
package/CONTRIBUTING.md
CHANGED
|
@@ -12,7 +12,7 @@ claude plugin install myco@myco-plugins
|
|
|
12
12
|
Then in any project:
|
|
13
13
|
|
|
14
14
|
```
|
|
15
|
-
/myco-
|
|
15
|
+
/myco-setup
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
This sets up the vault, configures your LLM backend, and starts capturing session knowledge.
|
|
@@ -58,15 +58,15 @@ claude plugin install myco
|
|
|
58
58
|
### 3. Initialize the vault
|
|
59
59
|
|
|
60
60
|
```
|
|
61
|
-
/myco-
|
|
61
|
+
/myco-setup
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
For dogfooding, the vault lives at `~/.myco/vaults/myco/` (configured via `MYCO_VAULT_DIR` in `.claude/settings.json`).
|
|
65
65
|
|
|
66
66
|
### 4. Verify
|
|
67
67
|
|
|
68
|
-
```
|
|
69
|
-
/
|
|
68
|
+
```bash
|
|
69
|
+
node dist/src/cli.js stats
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
## Development Workflow
|
|
@@ -95,7 +95,6 @@ myco/
|
|
|
95
95
|
├── .claude-plugin/ # Claude Code + VS Code plugin manifest + marketplace
|
|
96
96
|
├── .cursor-plugin/ # Cursor plugin manifest + marketplace
|
|
97
97
|
├── hooks/ # Hook registration shell scripts
|
|
98
|
-
├── commands/ # Slash commands (/myco-init, /myco-status, /myco-setup-llm)
|
|
99
98
|
├── skills/ # Agent skills
|
|
100
99
|
├── src/
|
|
101
100
|
│ ├── agents/ # Agent adapters (Claude Code, Cursor) — transcript parsing + image capture
|
package/README.md
CHANGED
|
@@ -103,7 +103,9 @@ var OllamaBackend = class _OllamaBackend {
|
|
|
103
103
|
// src/intelligence/lm-studio.ts
|
|
104
104
|
var ENDPOINT_CHAT = "/api/v1/chat";
|
|
105
105
|
var ENDPOINT_MODELS_LOAD = "/api/v1/models/load";
|
|
106
|
+
var ENDPOINT_MODELS_UNLOAD = "/api/v1/models/unload";
|
|
106
107
|
var ENDPOINT_MODELS_LIST = "/v1/models";
|
|
108
|
+
var ENDPOINT_MODELS_NATIVE = "/api/v1/models";
|
|
107
109
|
var ENDPOINT_EMBEDDINGS = "/v1/embeddings";
|
|
108
110
|
var LmStudioBackend = class _LmStudioBackend {
|
|
109
111
|
static DEFAULT_BASE_URL = "http://localhost:1234";
|
|
@@ -180,18 +182,29 @@ var LmStudioBackend = class _LmStudioBackend {
|
|
|
180
182
|
return { embedding, model: data.model, dimensions: embedding.length };
|
|
181
183
|
}
|
|
182
184
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* using the same model with different settings.
|
|
185
|
+
* Ensure a model instance is loaded with the desired settings.
|
|
186
|
+
* First checks for an existing compatible instance to reuse (prevents
|
|
187
|
+
* accumulation across daemon restarts), then loads a new one only if needed.
|
|
188
|
+
* Unloads incompatible instances of the same model to prevent resource exhaustion.
|
|
188
189
|
*/
|
|
189
190
|
async ensureLoaded(contextLength, gpuKvCache) {
|
|
190
191
|
const ctx = contextLength ?? this.contextWindow;
|
|
192
|
+
const kvCache = gpuKvCache ?? false;
|
|
193
|
+
const instances = await this.getLoadedInstances();
|
|
194
|
+
for (const instance of instances) {
|
|
195
|
+
const matchesContext = !ctx || instance.config.context_length === ctx;
|
|
196
|
+
const matchesKvCache = instance.config.offload_kv_cache_to_gpu === kvCache;
|
|
197
|
+
if (matchesContext && matchesKvCache) {
|
|
198
|
+
this.loadedInstanceId = instance.id;
|
|
199
|
+
await this.unloadIncompatibleInstances(instances, ctx, kvCache);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
await this.unloadIncompatibleInstances(instances, ctx, kvCache);
|
|
191
204
|
const body = {
|
|
192
205
|
model: this.model,
|
|
193
206
|
flash_attention: true,
|
|
194
|
-
offload_kv_cache_to_gpu:
|
|
207
|
+
offload_kv_cache_to_gpu: kvCache
|
|
195
208
|
};
|
|
196
209
|
if (ctx) {
|
|
197
210
|
body.context_length = ctx;
|
|
@@ -207,8 +220,47 @@ var LmStudioBackend = class _LmStudioBackend {
|
|
|
207
220
|
throw new Error(`LM Studio model load failed: ${response.status} ${errorBody.slice(0, 200)}`);
|
|
208
221
|
}
|
|
209
222
|
const loadResult = await response.json();
|
|
210
|
-
|
|
211
|
-
|
|
223
|
+
const instanceId = loadResult.id ?? loadResult.instance_id ?? loadResult.model_instance_id;
|
|
224
|
+
if (instanceId) {
|
|
225
|
+
this.loadedInstanceId = instanceId;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Query the LM Studio native API for loaded instances of this model.
|
|
230
|
+
* Returns an empty array if the API is unavailable or the model has no loaded instances.
|
|
231
|
+
*/
|
|
232
|
+
async getLoadedInstances() {
|
|
233
|
+
try {
|
|
234
|
+
const response = await fetch(`${this.baseUrl}${ENDPOINT_MODELS_NATIVE}`, {
|
|
235
|
+
signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS)
|
|
236
|
+
});
|
|
237
|
+
if (!response.ok) return [];
|
|
238
|
+
const data = await response.json();
|
|
239
|
+
const entry = data.models.find((m) => m.key === this.model);
|
|
240
|
+
return entry?.loaded_instances ?? [];
|
|
241
|
+
} catch {
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Unload instances of this model that don't match the desired settings.
|
|
247
|
+
* Best-effort — failures are silently ignored to avoid blocking the load path.
|
|
248
|
+
*/
|
|
249
|
+
async unloadIncompatibleInstances(instances, contextLength, gpuKvCache) {
|
|
250
|
+
for (const instance of instances) {
|
|
251
|
+
const matchesContext = !contextLength || instance.config.context_length === contextLength;
|
|
252
|
+
const matchesKvCache = instance.config.offload_kv_cache_to_gpu === gpuKvCache;
|
|
253
|
+
if (!matchesContext || !matchesKvCache) {
|
|
254
|
+
try {
|
|
255
|
+
await fetch(`${this.baseUrl}${ENDPOINT_MODELS_UNLOAD}`, {
|
|
256
|
+
method: "POST",
|
|
257
|
+
headers: { "Content-Type": "application/json" },
|
|
258
|
+
body: JSON.stringify({ model: instance.id }),
|
|
259
|
+
signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS)
|
|
260
|
+
});
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
}
|
|
212
264
|
}
|
|
213
265
|
}
|
|
214
266
|
async isAvailable() {
|
|
@@ -239,4 +291,4 @@ export {
|
|
|
239
291
|
OllamaBackend,
|
|
240
292
|
LmStudioBackend
|
|
241
293
|
};
|
|
242
|
-
//# sourceMappingURL=chunk-
|
|
294
|
+
//# sourceMappingURL=chunk-67R6EMYD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/intelligence/ollama.ts","../src/intelligence/lm-studio.ts"],"sourcesContent":["import type { LlmProvider, EmbeddingProvider, LlmResponse, EmbeddingResponse, LlmRequestOptions } from './llm.js';\nimport { estimateTokens, LLM_REQUEST_TIMEOUT_MS, EMBEDDING_REQUEST_TIMEOUT_MS, DAEMON_CLIENT_TIMEOUT_MS } from '../constants.js';\n\ninterface OllamaConfig {\n model?: string;\n base_url?: string;\n context_window?: number;\n max_tokens?: number;\n // Legacy fields (ignored, kept for backward compat during migration)\n embedding_model?: string;\n summary_model?: string;\n}\n\n// Ollama API endpoints\nconst ENDPOINT_GENERATE = '/api/generate';\nconst ENDPOINT_EMBED = '/api/embed';\nconst ENDPOINT_TAGS = '/api/tags';\n\nexport class OllamaBackend implements LlmProvider, EmbeddingProvider {\n static readonly DEFAULT_BASE_URL = 'http://localhost:11434';\n readonly name = 'ollama';\n private baseUrl: string;\n private model: string;\n private contextWindow: number;\n private defaultMaxTokens: number;\n\n constructor(config?: OllamaConfig) {\n this.baseUrl = config?.base_url ?? OllamaBackend.DEFAULT_BASE_URL;\n this.model = config?.model ?? config?.summary_model ?? 'llama3.2';\n this.contextWindow = config?.context_window ?? 8192;\n this.defaultMaxTokens = config?.max_tokens ?? 1024;\n }\n\n async summarize(prompt: string, opts?: LlmRequestOptions): Promise<LlmResponse> {\n const maxTokens = opts?.maxTokens ?? this.defaultMaxTokens;\n const contextLength = opts?.contextLength ?? this.contextWindow;\n const promptTokens = estimateTokens(prompt);\n const numCtx = Math.max(promptTokens + maxTokens, contextLength);\n\n const body: Record<string, unknown> = {\n model: this.model,\n prompt,\n stream: false,\n options: {\n num_ctx: numCtx,\n num_predict: maxTokens,\n },\n };\n\n // System prompt — sent as a separate field instead of concatenated into prompt\n if (opts?.systemPrompt) {\n body.system = opts.systemPrompt;\n }\n\n // Thinking control — false suppresses chain-of-thought for reasoning models\n if (opts?.reasoning) {\n body.think = opts.reasoning === 'off' ? false : opts.reasoning;\n }\n\n // Keep model loaded between requests (useful for digest cycles)\n if (opts?.keepAlive) {\n body.keep_alive = opts.keepAlive;\n }\n\n const response = await fetch(`${this.baseUrl}${ENDPOINT_GENERATE}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? LLM_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`Ollama summarize failed: ${response.status} ${errorBody.slice(0, 500)}`);\n }\n\n const data = await response.json() as { response: string; model: string };\n return { text: data.response, model: data.model };\n }\n\n async embed(text: string): Promise<EmbeddingResponse> {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_EMBED}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.model,\n input: text,\n }),\n signal: AbortSignal.timeout(EMBEDDING_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n throw new Error(`Ollama embed failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json() as { embeddings: number[][]; model: string };\n const embedding = data.embeddings[0];\n return { embedding, model: data.model, dimensions: embedding.length };\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_TAGS}`, {\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /** List available models on this Ollama instance. */\n async listModels(timeoutMs?: number): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_TAGS}`, {\n signal: AbortSignal.timeout(timeoutMs ?? DAEMON_CLIENT_TIMEOUT_MS),\n });\n const data = await response.json() as { models: Array<{ name: string }> };\n return data.models.map((m) => m.name);\n } catch {\n return [];\n }\n }\n}\n","import type { LlmProvider, EmbeddingProvider, LlmResponse, EmbeddingResponse, LlmRequestOptions } from './llm.js';\nimport { LLM_REQUEST_TIMEOUT_MS, EMBEDDING_REQUEST_TIMEOUT_MS, DAEMON_CLIENT_TIMEOUT_MS } from '../constants.js';\n\ninterface LmStudioConfig {\n model?: string;\n base_url?: string;\n context_window?: number;\n max_tokens?: number;\n // Legacy fields\n embedding_model?: string;\n summary_model?: string;\n}\n\n// LM Studio API endpoints\nconst ENDPOINT_CHAT = '/api/v1/chat';\nconst ENDPOINT_MODELS_LOAD = '/api/v1/models/load';\nconst ENDPOINT_MODELS_UNLOAD = '/api/v1/models/unload';\nconst ENDPOINT_MODELS_LIST = '/v1/models';\nconst ENDPOINT_MODELS_NATIVE = '/api/v1/models';\nconst ENDPOINT_EMBEDDINGS = '/v1/embeddings';\n\n/** Shape of a loaded instance from the LM Studio native models API. */\ninterface NativeLoadedInstance {\n id: string;\n config: {\n context_length: number;\n flash_attention: boolean;\n offload_kv_cache_to_gpu: boolean;\n };\n}\n\n/** Shape of a model entry from the LM Studio native models API. */\ninterface NativeModelEntry {\n type: string;\n key: string;\n loaded_instances: NativeLoadedInstance[];\n}\n\nexport class LmStudioBackend implements LlmProvider, EmbeddingProvider {\n static readonly DEFAULT_BASE_URL = 'http://localhost:1234';\n readonly name = 'lm-studio';\n private baseUrl: string;\n private model: string;\n private loadedInstanceId: string | null = null;\n private contextWindow: number | undefined;\n private defaultMaxTokens: number;\n\n constructor(config?: LmStudioConfig) {\n this.baseUrl = config?.base_url ?? LmStudioBackend.DEFAULT_BASE_URL;\n this.model = config?.model ?? config?.summary_model ?? 'llama3.2';\n this.contextWindow = config?.context_window;\n this.defaultMaxTokens = config?.max_tokens ?? 1024;\n }\n\n /**\n * Generate text using LM Studio's native REST API (/api/v1/chat).\n * Supports per-request context_length, reasoning control, and system_prompt.\n */\n async summarize(prompt: string, opts?: LlmRequestOptions): Promise<LlmResponse> {\n const maxTokens = opts?.maxTokens ?? this.defaultMaxTokens;\n\n const body: Record<string, unknown> = {\n model: this.loadedInstanceId ?? this.model,\n input: prompt,\n max_output_tokens: maxTokens,\n store: false,\n };\n\n // Only set context_length if we haven't pre-loaded the model\n // (pre-loaded models already have the correct context via ensureLoaded)\n if (!this.loadedInstanceId) {\n const contextLength = opts?.contextLength ?? this.contextWindow;\n if (contextLength) {\n body.context_length = contextLength;\n }\n }\n\n // System prompt — sent separately from user content\n if (opts?.systemPrompt) {\n body.system_prompt = opts.systemPrompt;\n }\n\n // Reasoning control — 'off' suppresses chain-of-thought for reasoning models\n if (opts?.reasoning) {\n body.reasoning = opts.reasoning;\n }\n\n const response = await fetch(`${this.baseUrl}${ENDPOINT_CHAT}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(opts?.timeoutMs ?? LLM_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`LM Studio summarize failed: ${response.status} ${errorBody.slice(0, 500)}`);\n }\n\n const data = await response.json() as {\n model_instance_id: string;\n output: Array<{ type: string; content: string }>;\n };\n const messageOutput = data.output.find((o) => o.type === 'message');\n const text = messageOutput?.content ?? '';\n return { text, model: data.model_instance_id };\n }\n\n /**\n * Generate embeddings using LM Studio's OpenAI-compatible endpoint.\n * (The native API doesn't have an embedding endpoint — OpenAI-compat is fine here.)\n */\n async embed(text: string): Promise<EmbeddingResponse> {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_EMBEDDINGS}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.model,\n input: text,\n }),\n signal: AbortSignal.timeout(EMBEDDING_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n throw new Error(`LM Studio embed failed: ${response.status}`);\n }\n\n const data = await response.json() as {\n data: Array<{ embedding: number[] }>;\n model: string;\n };\n const embedding = data.data[0].embedding;\n return { embedding, model: data.model, dimensions: embedding.length };\n }\n\n /**\n * Ensure a model instance is loaded with the desired settings.\n * First checks for an existing compatible instance to reuse (prevents\n * accumulation across daemon restarts), then loads a new one only if needed.\n * Unloads incompatible instances of the same model to prevent resource exhaustion.\n */\n async ensureLoaded(contextLength?: number, gpuKvCache?: boolean): Promise<void> {\n const ctx = contextLength ?? this.contextWindow;\n const kvCache = gpuKvCache ?? false;\n\n // Query native API for existing loaded instances of this model\n const instances = await this.getLoadedInstances();\n\n // Check for a compatible instance we can reuse\n for (const instance of instances) {\n const matchesContext = !ctx || instance.config.context_length === ctx;\n const matchesKvCache = instance.config.offload_kv_cache_to_gpu === kvCache;\n if (matchesContext && matchesKvCache) {\n this.loadedInstanceId = instance.id;\n // Unload any incompatible instances (best effort, don't block on failure)\n await this.unloadIncompatibleInstances(instances, ctx, kvCache);\n return;\n }\n }\n\n // Unload incompatible instances before loading to free resources\n await this.unloadIncompatibleInstances(instances, ctx, kvCache);\n\n // No compatible instance found — load a new one\n const body: Record<string, unknown> = {\n model: this.model,\n flash_attention: true,\n offload_kv_cache_to_gpu: kvCache,\n };\n if (ctx) {\n body.context_length = ctx;\n }\n\n const response = await fetch(`${this.baseUrl}${ENDPOINT_MODELS_LOAD}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(LLM_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`LM Studio model load failed: ${response.status} ${errorBody.slice(0, 200)}`);\n }\n\n // Capture instance ID — LM Studio may return it under different field names\n const loadResult = await response.json() as Record<string, unknown>;\n const instanceId = (loadResult.id ?? loadResult.instance_id ?? loadResult.model_instance_id) as string | undefined;\n if (instanceId) {\n this.loadedInstanceId = instanceId;\n }\n }\n\n /**\n * Query the LM Studio native API for loaded instances of this model.\n * Returns an empty array if the API is unavailable or the model has no loaded instances.\n */\n private async getLoadedInstances(): Promise<NativeLoadedInstance[]> {\n try {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_MODELS_NATIVE}`, {\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n if (!response.ok) return [];\n\n const data = await response.json() as { models: NativeModelEntry[] };\n const entry = data.models.find((m) => m.key === this.model);\n return entry?.loaded_instances ?? [];\n } catch {\n return [];\n }\n }\n\n /**\n * Unload instances of this model that don't match the desired settings.\n * Best-effort — failures are silently ignored to avoid blocking the load path.\n */\n private async unloadIncompatibleInstances(\n instances: NativeLoadedInstance[],\n contextLength: number | undefined,\n gpuKvCache: boolean,\n ): Promise<void> {\n for (const instance of instances) {\n const matchesContext = !contextLength || instance.config.context_length === contextLength;\n const matchesKvCache = instance.config.offload_kv_cache_to_gpu === gpuKvCache;\n if (!matchesContext || !matchesKvCache) {\n try {\n await fetch(`${this.baseUrl}${ENDPOINT_MODELS_UNLOAD}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: instance.id }),\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n } catch {\n // Best effort — don't fail the load if cleanup fails\n }\n }\n }\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_MODELS_LIST}`, {\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /** List available models on this LM Studio instance. */\n async listModels(timeoutMs?: number): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseUrl}${ENDPOINT_MODELS_LIST}`, {\n signal: AbortSignal.timeout(timeoutMs ?? DAEMON_CLIENT_TIMEOUT_MS),\n });\n const data = await response.json() as { data: Array<{ id: string }> };\n return data.data.map((m) => m.id);\n } catch {\n return [];\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -21144,6 +21144,8 @@ var DigestSchema = external_exports.object({
|
|
|
21144
21144
|
});
|
|
21145
21145
|
var MycoConfigSchema = external_exports.object({
|
|
21146
21146
|
version: external_exports.literal(2),
|
|
21147
|
+
/** Tracks which migrations have been applied. Managed automatically. */
|
|
21148
|
+
config_version: external_exports.number().int().nonnegative().default(0),
|
|
21147
21149
|
intelligence: IntelligenceSchema.default(() => IntelligenceSchema.parse({})),
|
|
21148
21150
|
daemon: DaemonSchema.default(() => DaemonSchema.parse({})),
|
|
21149
21151
|
capture: CaptureSchema.default(() => CaptureSchema.parse({})),
|
|
@@ -21176,4 +21178,4 @@ export {
|
|
|
21176
21178
|
external_exports,
|
|
21177
21179
|
MycoConfigSchema
|
|
21178
21180
|
};
|
|
21179
|
-
//# sourceMappingURL=chunk-
|
|
21181
|
+
//# sourceMappingURL=chunk-6UJWI4IW.js.map
|