chore: update compiled output, docs, and CLAUDE.md model defaults
This commit is contained in:
@@ -74,7 +74,7 @@ Entry: `src/main.ts` → bundled to `main.js` via esbuild (CJS, ES2018 target).
|
|||||||
| Field | Default | Description |
|
| Field | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `apiKey` | `""` | Anthropic API key |
|
| `apiKey` | `""` | Anthropic API key |
|
||||||
| `model` | `claude-opus-4-5-20251101` | Claude model ID |
|
| `model` | `claude-opus-4-6` | Claude model ID |
|
||||||
| `maxTokens` | `8192` | Max output tokens (1024–16000) |
|
| `maxTokens` | `8192` | Max output tokens (1024–16000) |
|
||||||
| `maxContextNotes` | `6` | TF-IDF/embedding context notes per query |
|
| `maxContextNotes` | `6` | TF-IDF/embedding context notes per query |
|
||||||
| `maxCharsPerNote` | `2500` | Characters per context note |
|
| `maxCharsPerNote` | `2500` | Characters per context note |
|
||||||
@@ -118,4 +118,4 @@ Copy `main.js`, `manifest.json`, `styles.css` into `.obsidian/plugins/memex-chat
|
|||||||
|
|
||||||
## Models (SettingsTab.ts)
|
## Models (SettingsTab.ts)
|
||||||
|
|
||||||
Default: `claude-opus-4-5-20251101`. Update `MODELS` array and `DEFAULT_SETTINGS.model` when adding new model IDs.
|
Default: `claude-opus-4-6`. Update `MODELS` array and `DEFAULT_SETTINGS.model` when adding new model IDs.
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
# Fetch Models Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Add an "Aktualisieren" button next to the model dropdown in settings that fetches the 3 newest Claude models from the Anthropic API and repopulates the dropdown.
|
||||||
|
|
||||||
|
**Architecture:** `ClaudeClient` gains a `fetchModels()` method (reusing existing `requestUrl`/`headers` patterns). `SettingsTab` captures the `DropdownComponent` and `ButtonComponent` references, wires the button to call `fetchModels`, and rebuilds the dropdown on success.
|
||||||
|
|
||||||
|
**Tech Stack:** TypeScript, Obsidian plugin API (`requestUrl`, `Setting`, `DropdownComponent`, `ButtonComponent`, `Notice`), Anthropic Models API (`GET /v1/models`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Map
|
||||||
|
|
||||||
|
| File | Change |
|
||||||
|
|---|---|
|
||||||
|
| `src/ClaudeClient.ts` | Add `fetchModels(apiKey)` method |
|
||||||
|
| `src/SettingsTab.ts` | Update imports; refactor "Modell" `Setting` to capture dropdown + add button |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Add `fetchModels` to `ClaudeClient`
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `src/ClaudeClient.ts`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add the method after the `chat()` method**
|
||||||
|
|
||||||
|
In `src/ClaudeClient.ts`, add after line 86 (after `chat()`'s closing brace):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
/** Fetch the 3 newest Claude models from the Anthropic Models API. */
|
||||||
|
async fetchModels(apiKey: string): Promise<{ id: string; name: string }[]> {
|
||||||
|
const response = await requestUrl({
|
||||||
|
url: "https://api.anthropic.com/v1/models",
|
||||||
|
method: "GET",
|
||||||
|
headers: this.headers(apiKey),
|
||||||
|
throw: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status >= 400) {
|
||||||
|
throw new Error(`API Error ${response.status}: ${response.text}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: { id: string; created: number }[] = response.json.data ?? [];
|
||||||
|
if (data.length === 0) {
|
||||||
|
throw new Error("No models returned");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
.sort((a, b) => b.created - a.created)
|
||||||
|
.slice(0, 3)
|
||||||
|
.map((m) => ({ id: m.id, name: m.id }));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify build passes**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: no TypeScript errors, `main.js` written successfully.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add src/ClaudeClient.ts
|
||||||
|
git commit -m "feat: add fetchModels to ClaudeClient"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Update SettingsTab — imports and model setting
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `src/SettingsTab.ts:1` (import line)
|
||||||
|
- Modify: `src/SettingsTab.ts:151-160` (the "Modell" Setting block)
|
||||||
|
|
||||||
|
- [ ] **Step 1: Extend the import from `"obsidian"`**
|
||||||
|
|
||||||
|
Replace the current import line 1:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||||
|
```
|
||||||
|
|
||||||
|
With:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { App, ButtonComponent, DropdownComponent, Notice, PluginSettingTab, Setting } from "obsidian";
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Replace the "Modell" Setting block**
|
||||||
|
|
||||||
|
Replace lines 151–160:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Modell")
|
||||||
|
.setDesc("Welches Claude-Modell verwenden?")
|
||||||
|
.addDropdown((drop) => {
|
||||||
|
for (const m of MODELS) drop.addOption(m.id, m.name);
|
||||||
|
drop.setValue(this.plugin.settings.model).onChange(async (value) => {
|
||||||
|
this.plugin.settings.model = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
With:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let modelDrop: DropdownComponent;
|
||||||
|
let refreshBtn: ButtonComponent;
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Modell")
|
||||||
|
.setDesc("Welches Claude-Modell verwenden?")
|
||||||
|
.addDropdown((drop) => {
|
||||||
|
modelDrop = drop;
|
||||||
|
for (const m of MODELS) drop.addOption(m.id, m.name);
|
||||||
|
drop.setValue(this.plugin.settings.model).onChange(async (value) => {
|
||||||
|
this.plugin.settings.model = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.addButton((btn) => {
|
||||||
|
refreshBtn = btn;
|
||||||
|
btn.setButtonText("Aktualisieren").onClick(async () => {
|
||||||
|
const prev = modelDrop.getValue();
|
||||||
|
refreshBtn.setDisabled(true);
|
||||||
|
refreshBtn.setButtonText("...");
|
||||||
|
try {
|
||||||
|
const models = await this.plugin.claude.fetchModels(this.plugin.settings.apiKey);
|
||||||
|
modelDrop.selectEl.empty();
|
||||||
|
for (const m of models) modelDrop.addOption(m.id, m.name);
|
||||||
|
modelDrop.setValue(prev);
|
||||||
|
this.plugin.settings.model = modelDrop.getValue();
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
} catch (err) {
|
||||||
|
new Notice("Modelle konnten nicht geladen werden: " + (err as Error).message);
|
||||||
|
} finally {
|
||||||
|
refreshBtn.setDisabled(false);
|
||||||
|
refreshBtn.setButtonText("Aktualisieren");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Verify build passes**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: no TypeScript errors, `main.js` written successfully.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Manual smoke test in Obsidian**
|
||||||
|
|
||||||
|
1. Copy `main.js`, `manifest.json`, `styles.css` to `.obsidian/plugins/memex-chat/` in your vault
|
||||||
|
2. Reload the plugin (or restart Obsidian)
|
||||||
|
3. Open Settings → Memex Chat
|
||||||
|
4. Confirm the "Modell" row has a dropdown and an "Aktualisieren" button
|
||||||
|
5. With a valid API key set, click "Aktualisieren" — button should show "...", then restore; dropdown should show 3 model IDs
|
||||||
|
6. With no API key, click "Aktualisieren" — a Notice should appear with an error message; dropdown should be unchanged
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add src/SettingsTab.ts
|
||||||
|
git commit -m "feat: add Aktualisieren button to fetch models from API"
|
||||||
|
```
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Fetch Models Design
|
||||||
|
|
||||||
|
**Date:** 2026-03-27
|
||||||
|
**Status:** Approved
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Add an "Aktualisieren" button to the Model setting in the settings tab. When clicked, it fetches the 3 newest Claude models from the Anthropic Models API and updates the dropdown. Falls back to the hardcoded `MODELS` list if the request fails or returns no models.
|
||||||
|
|
||||||
|
## ClaudeClient changes
|
||||||
|
|
||||||
|
Add a new method `fetchModels(apiKey: string): Promise<{id: string, name: string}[]>` to `ClaudeClient`.
|
||||||
|
|
||||||
|
- URL: `"https://api.anthropic.com/v1/models"` — inline string or a separate private constant; **do not use or modify `baseUrl`** (which points to `/v1/messages`)
|
||||||
|
- Call `requestUrl` with `throw: false` (same pattern as `streamChat`/`chat`) and `this.headers(apiKey)`
|
||||||
|
- Response shape: `{ data: [{ id: string, created: number, display_name: string, ... }] }`
|
||||||
|
- Throw on `response.status >= 400` with the response text
|
||||||
|
- If `data` is empty, throw an error ("No models returned") — do not return an empty array
|
||||||
|
- Sort `data` descending by `created`, take top 3
|
||||||
|
- Return `{ id, name: id }` for each — use `id` as the display name (not `display_name`). Note: fetched entries will show raw IDs (e.g. `claude-opus-4-6`) while hardcoded `MODELS` show human-friendly names (e.g. `"Claude Opus 4.6 (Stärkste)"`). This is intentional — keeps the implementation simple and avoids relying on API-provided display strings.
|
||||||
|
|
||||||
|
## SettingsTab changes
|
||||||
|
|
||||||
|
**Import addition:** Add `Notice, ButtonComponent, DropdownComponent` to the `import { ... } from "obsidian"` line.
|
||||||
|
|
||||||
|
Convert the existing "Modell" `Setting` to capture both the `DropdownComponent` and `ButtonComponent` references by chaining `addDropdown()` and `addButton()` on the same `Setting` instance:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let modelDrop: DropdownComponent;
|
||||||
|
let refreshBtn: ButtonComponent;
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Modell")
|
||||||
|
.setDesc("Welches Claude-Modell verwenden?")
|
||||||
|
.addDropdown((drop) => {
|
||||||
|
modelDrop = drop;
|
||||||
|
for (const m of MODELS) drop.addOption(m.id, m.name);
|
||||||
|
drop.setValue(this.plugin.settings.model).onChange(async (value) => {
|
||||||
|
this.plugin.settings.model = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.addButton((btn) => {
|
||||||
|
refreshBtn = btn;
|
||||||
|
btn.setButtonText("Aktualisieren").onClick(async () => { /* see click flow */ });
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Click flow:**
|
||||||
|
1. Capture current value: `const prev = modelDrop.getValue()`
|
||||||
|
2. `refreshBtn.setDisabled(true)` and `refreshBtn.setButtonText("...")`
|
||||||
|
3. In a try/catch/finally:
|
||||||
|
- **try:** Call `this.plugin.claude.fetchModels(this.plugin.settings.apiKey)`
|
||||||
|
- On success: clear dropdown with `modelDrop.selectEl.empty()`, repopulate via `modelDrop.addOption(id, name)` for each fetched model, then set value to `prev` if it exists among the fetched ids, otherwise the first fetched id; save via `this.plugin.settings.model = modelDrop.getValue(); await this.plugin.saveSettings()`
|
||||||
|
- **catch:** `new Notice("Modelle konnten nicht geladen werden: " + err.message)` — dropdown is **not** modified on error (hardcoded options remain)
|
||||||
|
- **finally:** `refreshBtn.setDisabled(false)` and `refreshBtn.setButtonText("Aktualisieren")`
|
||||||
|
|
||||||
|
**Fallback:** The hardcoded `MODELS` array in `SettingsTab.ts` is unchanged and remains the initial population of the dropdown on every settings open.
|
||||||
|
|
||||||
|
## Data flow
|
||||||
|
|
||||||
|
```
|
||||||
|
[Aktualisieren button click]
|
||||||
|
→ capture prev = modelDrop.getValue()
|
||||||
|
→ disable button, show "..."
|
||||||
|
→ this.plugin.claude.fetchModels(apiKey) [throw: false, separate URL]
|
||||||
|
→ throw if status >= 400 or data empty
|
||||||
|
→ sort by created desc, take 3
|
||||||
|
→ return [{id, name: id}]
|
||||||
|
→ clear selectEl, repopulate, restore selection
|
||||||
|
→ save model to settings
|
||||||
|
→ finally: restore button
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
| Scenario | Behaviour |
|
||||||
|
|---|---|
|
||||||
|
| No API key (401) | Notice shown; dropdown unchanged |
|
||||||
|
| Network failure | Notice shown; dropdown unchanged |
|
||||||
|
| Empty `data` array | Treated as error; Notice shown; dropdown unchanged |
|
||||||
|
| Fewer than 3 models returned | Take all returned (no error) |
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
- Persisting fetched models across restarts
|
||||||
|
- Auto-fetching on settings open or plugin startup
|
||||||
|
- Configurable count of models to show
|
||||||
|
- Updating `DEFAULT_SETTINGS.model` after a fetch
|
||||||
@@ -32725,13 +32725,37 @@ var ClaudeClient = class {
|
|||||||
}
|
}
|
||||||
return response.json.content?.[0]?.text ?? "";
|
return response.json.content?.[0]?.text ?? "";
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Fetch Claude models from the Anthropic Models API.
|
||||||
|
* Returns the 2 newest versions of each family (opus, sonnet, haiku), in that order.
|
||||||
|
*/
|
||||||
|
async fetchModels(apiKey) {
|
||||||
|
const response = await (0, import_obsidian2.requestUrl)({
|
||||||
|
url: "https://api.anthropic.com/v1/models",
|
||||||
|
method: "GET",
|
||||||
|
headers: this.headers(apiKey),
|
||||||
|
throw: false
|
||||||
|
});
|
||||||
|
if (response.status >= 400) {
|
||||||
|
throw new Error(`API Error ${response.status}: ${response.text}`);
|
||||||
|
}
|
||||||
|
const data = response.json.data ?? [];
|
||||||
|
if (data.length === 0) {
|
||||||
|
throw new Error("No models returned");
|
||||||
|
}
|
||||||
|
const sorted = data.sort((a, b) => b.created - a.created);
|
||||||
|
const families = ["opus", "sonnet", "haiku"];
|
||||||
|
return families.flatMap(
|
||||||
|
(family) => sorted.filter((m) => m.id.includes(family)).slice(0, 2).map((m) => ({ id: m.id, name: m.id }))
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/SettingsTab.ts
|
// src/SettingsTab.ts
|
||||||
var import_obsidian3 = require("obsidian");
|
var import_obsidian3 = require("obsidian");
|
||||||
var DEFAULT_SETTINGS = {
|
var DEFAULT_SETTINGS = {
|
||||||
apiKey: "",
|
apiKey: "",
|
||||||
model: "claude-opus-4-5-20251101",
|
model: "claude-opus-4-6",
|
||||||
maxTokens: 8192,
|
maxTokens: 8192,
|
||||||
maxContextNotes: 6,
|
maxContextNotes: 6,
|
||||||
maxCharsPerNote: 2500,
|
maxCharsPerNote: 2500,
|
||||||
@@ -32768,8 +32792,8 @@ Wenn du Fragen beantwortest:
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
var MODELS = [
|
var MODELS = [
|
||||||
{ id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (St\xE4rkste)" },
|
{ id: "claude-opus-4-6", name: "Claude Opus 4.6 (St\xE4rkste)" },
|
||||||
{ id: "claude-sonnet-4-5-20250929", name: "Claude Sonnet 4.5 (Empfohlen)" },
|
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6 (Empfohlen)" },
|
||||||
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }
|
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }
|
||||||
];
|
];
|
||||||
var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab {
|
var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab {
|
||||||
@@ -32827,13 +32851,37 @@ var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab {
|
|||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new import_obsidian3.Setting(containerEl).setName("Modell").setDesc("Welches Claude-Modell verwenden?").addDropdown((drop) => {
|
let modelDrop;
|
||||||
|
let refreshBtn;
|
||||||
|
new import_obsidian3.Setting(containerEl).setName("Modell").setDesc("Welches Claude-Modell verwenden? (Aktualisieren zeigt Roh-IDs)").addDropdown((drop) => {
|
||||||
|
modelDrop = drop;
|
||||||
for (const m of MODELS)
|
for (const m of MODELS)
|
||||||
drop.addOption(m.id, m.name);
|
drop.addOption(m.id, m.name);
|
||||||
drop.setValue(this.plugin.settings.model).onChange(async (value) => {
|
drop.setValue(this.plugin.settings.model).onChange(async (value) => {
|
||||||
this.plugin.settings.model = value;
|
this.plugin.settings.model = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
});
|
});
|
||||||
|
}).addButton((btn) => {
|
||||||
|
refreshBtn = btn;
|
||||||
|
btn.setButtonText("Aktualisieren").onClick(async () => {
|
||||||
|
const prev = modelDrop.getValue();
|
||||||
|
refreshBtn.setDisabled(true);
|
||||||
|
refreshBtn.setButtonText("...");
|
||||||
|
try {
|
||||||
|
const models = await this.plugin.claude.fetchModels(this.plugin.settings.apiKey);
|
||||||
|
modelDrop.selectEl.empty();
|
||||||
|
for (const m of models)
|
||||||
|
modelDrop.addOption(m.id, m.name);
|
||||||
|
modelDrop.setValue(prev);
|
||||||
|
this.plugin.settings.model = modelDrop.getValue();
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
} catch (err) {
|
||||||
|
new import_obsidian3.Notice("Modelle konnten nicht geladen werden: " + err.message);
|
||||||
|
} finally {
|
||||||
|
refreshBtn.setDisabled(false);
|
||||||
|
refreshBtn.setButtonText("Aktualisieren");
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
new import_obsidian3.Setting(containerEl).setName("Max. Antwort-Tokens").setDesc("Maximale L\xE4nge der Claude-Antwort. F\xFCr lange Analysen (z.B. Monthly Check) h\xF6her einstellen. (1024\u201316000)").addSlider(
|
new import_obsidian3.Setting(containerEl).setName("Max. Antwort-Tokens").setDesc("Maximale L\xE4nge der Claude-Antwort. F\xFCr lange Analysen (z.B. Monthly Check) h\xF6her einstellen. (1024\u201316000)").addSlider(
|
||||||
(slider) => slider.setLimits(1024, 16e3, 512).setValue(this.plugin.settings.maxTokens).setDynamicTooltip().onChange(async (value) => {
|
(slider) => slider.setLimits(1024, 16e3, 512).setValue(this.plugin.settings.maxTokens).setDynamicTooltip().onChange(async (value) => {
|
||||||
@@ -33314,6 +33362,12 @@ var MemexChatPlugin = class extends import_obsidian5.Plugin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.addSettingTab(new MemexChatSettingsTab(this.app, this));
|
this.addSettingTab(new MemexChatSettingsTab(this.app, this));
|
||||||
|
this.registerEvent(
|
||||||
|
this.app.vault.on("modify", (file) => {
|
||||||
|
if (this.embedSearch && file instanceof import_obsidian5.TFile && file.extension === "md")
|
||||||
|
this.embedSearch.reembedFile(file);
|
||||||
|
})
|
||||||
|
);
|
||||||
this.app.workspace.onLayoutReady(() => {
|
this.app.workspace.onLayoutReady(() => {
|
||||||
if (!this.search.isIndexed()) {
|
if (!this.search.isIndexed()) {
|
||||||
this.search.priorityProperties = this.settings.contextProperties;
|
this.search.priorityProperties = this.settings.contextProperties;
|
||||||
@@ -33366,24 +33420,19 @@ var MemexChatPlugin = class extends import_obsidian5.Plugin {
|
|||||||
this.embedSearch = new EmbedSearch(this.app, this.settings.embeddingModel);
|
this.embedSearch = new EmbedSearch(this.app, this.settings.embeddingModel);
|
||||||
this.embedSearch.excludeFolders = this.settings.embedExcludeFolders ?? [];
|
this.embedSearch.excludeFolders = this.settings.embedExcludeFolders ?? [];
|
||||||
this.embedSearch.contextProperties = this.settings.contextProperties ?? [];
|
this.embedSearch.contextProperties = this.settings.contextProperties ?? [];
|
||||||
this.registerEvent(
|
const modelShort = this.settings.embeddingModel.split("/").pop() ?? this.settings.embeddingModel;
|
||||||
this.app.vault.on("modify", (file) => {
|
const notice = new import_obsidian5.Notice(`Memex [${modelShort}]: Embedding wird vorbereitet\u2026`, 0);
|
||||||
if (this.embedSearch && file instanceof import_obsidian5.TFile && file.extension === "md")
|
|
||||||
this.embedSearch.reembedFile(file);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
const notice = new import_obsidian5.Notice("Memex: Embedding wird vorbereitet\u2026", 0);
|
|
||||||
this.embedSearch.onModelStatus = (status) => {
|
this.embedSearch.onModelStatus = (status) => {
|
||||||
notice.setMessage(`Memex: ${status}`);
|
notice.setMessage(`Memex [${modelShort}]: ${status}`);
|
||||||
};
|
};
|
||||||
this.embedSearch.onProgress = (done, total, speed) => {
|
this.embedSearch.onProgress = (done, total, speed) => {
|
||||||
const speedStr = speed > 0 ? ` \u2022 ${speed.toFixed(1)} N/s` : "";
|
const speedStr = speed > 0 ? ` \u2022 ${speed.toFixed(1)} N/s` : "";
|
||||||
const remaining = speed > 0 && done < total ? (total - done) / speed : 0;
|
const remaining = speed > 0 && done < total ? (total - done) / speed : 0;
|
||||||
const eta = remaining > 0 ? ` \u2022 ~${remaining < 60 ? Math.ceil(remaining) + "s" : Math.ceil(remaining / 60) + "min"}` : "";
|
const eta = remaining > 0 ? ` \u2022 ~${remaining < 60 ? Math.ceil(remaining) + "s" : Math.ceil(remaining / 60) + "min"}` : "";
|
||||||
notice.setMessage(`Memex Embedding: ${done}/${total}${speedStr}${eta}`);
|
notice.setMessage(`Memex [${modelShort}]: ${done}/${total}${speedStr}${eta}`);
|
||||||
};
|
};
|
||||||
this.waitForSyncIdle(notice).then(() => this.embedSearch?.buildIndex()).then(() => {
|
this.waitForSyncIdle(notice).then(() => this.embedSearch?.buildIndex()).then(() => {
|
||||||
notice.setMessage(`\u2713 Memex: ${this.app.vault.getMarkdownFiles().length} Notizen eingebettet`);
|
notice.setMessage(`\u2713 Memex [${modelShort}]: ${this.app.vault.getMarkdownFiles().length} Notizen eingebettet`);
|
||||||
setTimeout(() => notice.hide(), 4e3);
|
setTimeout(() => notice.hide(), 4e3);
|
||||||
this.notifyRelatedView();
|
this.notifyRelatedView();
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user