Update README with new features and fix streaming state cleanup
Expand documentation for agent modes, workflows, auto-organizer, structured memory, tool telemetry, and enhanced context sources. Set `isThinking` to false when finalizing assistant messages to ensure UI state resets correctly.
This commit is contained in:
@@ -4,13 +4,18 @@ A plugin that integrates [Ollama](https://ollama.ai) with Obsidian, allowing you
|
||||
|
||||
## Features
|
||||
|
||||
- Chat with Ollama models directly in Obsidian
|
||||
- Vault context search — the assistant can reference your notes
|
||||
- **Chat with Ollama models** directly in Obsidian with streaming responses
|
||||
- **Vault context search** — the assistant can reference your notes via semantic (RAG) or keyword search
|
||||
- **Agent Modes** — selectable chat modes (Ask, Edit, Organize, Research, Workflow) that change available tools, system prompts, and preview behaviour
|
||||
- **Tool integration** — create, read, search, append, edit, rename, move, delete notes, and insert wiki-links
|
||||
- **Structured Memory** — persist conversation summaries, user preferences, and learned facts across sessions
|
||||
- **Tool Telemetry** — track which tools were called, which notes were searched, and LLM token usage
|
||||
- **Semantic/RAG vault indexing** — automatically index your vault into a vector database for intelligent retrieval
|
||||
- Tool integration — create files based on chat responses
|
||||
- Streaming responses
|
||||
- Semantic response cache — repeated or similar queries are answered instantly without hitting the model (requires ChromaDB)
|
||||
- Customisable model, URL, and cache settings
|
||||
- **Semantic response cache** — repeated or similar queries are answered instantly without hitting the model
|
||||
- **Workflow Engine** — execute multi-step AI workflows via `/workflow` commands
|
||||
- **Auto-Organizer** — AI-powered auto-tagging and auto-linking with dry-run preview and folder scoping
|
||||
- **Obsidian MetadataCache integration** — frontmatter, tags, links, and headings are read via Obsidian's built-in cache instead of raw regex parsing
|
||||
- Customisable model, URL, cache, and memory settings
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -106,6 +111,7 @@ Open **Settings → Ollama Settings** to configure the plugin.
|
||||
|---------|---------|-------------|
|
||||
| Ollama URL | `http://localhost:11434` | Base URL of your Ollama instance |
|
||||
| Model | `llama3` | Model used for chat responses |
|
||||
| **Default Agent Mode** | `Ask` | Default chat mode (Ask, Edit, Organize, Research, Workflow) |
|
||||
| Vault Search Limit | `5` | Maximum number of vault entries to include in context |
|
||||
| Max Context Length | `8000` | Maximum characters of vault content sent to the AI per message |
|
||||
| Max Message History | `50` | Maximum number of messages kept in conversation history |
|
||||
@@ -118,8 +124,24 @@ Open **Settings → Ollama Settings** to configure the plugin.
|
||||
| Enable Semantic Cache | Off | Cache responses for fast repeated queries |
|
||||
| ChromaDB URL | `http://localhost:8000` | URL of your running ChromaDB instance |
|
||||
| Cache Embedding Model | `nomic-embed-text` | Ollama model used to generate cache embeddings |
|
||||
| Cache Similarity Threshold | `0.85` | Minimum cosine similarity (0–1) for a cache hit — higher values require closer matches |
|
||||
| Clear Semantic Cache | — | Button to wipe all cached responses from ChromaDB |
|
||||
| Cache Similarity Threshold | `0.85` | Minimum cosine similarity (0–1) for a cache hit |
|
||||
| Clear Semantic Cache | — | Button to wipe all cached responses |
|
||||
| **Enable Auto-Tagging** | Off | Automatically suggest and apply tags to untagged notes |
|
||||
| Max Tags Per Note | `5` | Maximum tags to generate per note |
|
||||
| Normalize Tags | On | Normalize generated tags against existing vault vocabulary |
|
||||
| Target Folder (Auto-Tag) | — | Restrict auto-tagging to a specific folder |
|
||||
| **Enable Auto-Linking** | Off | Add "Related Notes" sections based on semantic similarity |
|
||||
| Max Links Per Note | `3` | Maximum related note links to insert |
|
||||
| Target Folder (Auto-Link) | — | Restrict auto-linking to a specific folder |
|
||||
| Dry Run Mode (Auto-Link) | Off | Preview proposed links without applying them |
|
||||
| **Enable Structured Memory** | On | Inject remembered context from past sessions into prompts |
|
||||
| Max Conversation Summaries | `10` | Maximum past conversation summaries to retain |
|
||||
| Max User Preferences | `20` | Maximum user preferences to retain |
|
||||
| Max Learned Facts | `50` | Maximum learned facts to retain |
|
||||
| Clear Structured Memory | — | Button to delete all stored memory |
|
||||
| **Enable Tool Telemetry** | On | Record tool calls, searches, and LLM token counts |
|
||||
| Max Telemetry Entries | `100` | Maximum telemetry events to retain |
|
||||
| Clear Tool Telemetry | — | Button to delete all recorded telemetry |
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -129,6 +151,52 @@ Open **Settings → Ollama Settings** to configure the plugin.
|
||||
4. Press **Shift+Enter** to insert a line break
|
||||
5. Click **New Chat** to start a fresh conversation
|
||||
|
||||
### Agent Modes
|
||||
|
||||
The chat view includes a mode selector dropdown. Each mode changes the assistant's behaviour:
|
||||
|
||||
| Mode | Tools Available | Preview Required | Use Case |
|
||||
|------|----------------|------------------|----------|
|
||||
| **Ask** | Read, Search | No | Answer questions using vault context |
|
||||
| **Edit** | All tools | Yes | Create, modify, and manage notes |
|
||||
| **Organize** | Read, Search, Frontmatter, Rename, Move, Link | Yes | Tag, rename, move, and link notes |
|
||||
| **Research** | Read, Search | No | Deep vault search and synthesis |
|
||||
| **Workflow** | None (uses `/workflow`) | No | Execute multi-step AI workflows |
|
||||
|
||||
When a mode requires preview (Edit, Organize), write operations like `create_note` or `delete_note` show a card with a before/after diff and **Apply** / **Cancel** buttons. Ask and Research modes execute write tools immediately without preview.
|
||||
|
||||
### Workflows
|
||||
|
||||
Type `/workflow` followed by a description to trigger the workflow engine. The AI will generate a multi-step workflow plan, then execute it step-by-step. Example:
|
||||
|
||||
```
|
||||
/workflow Find all notes tagged "meeting", summarise them, and create a "Meeting Summary" note
|
||||
```
|
||||
|
||||
### Auto-Organizer
|
||||
|
||||
Use the command palette to trigger:
|
||||
- **Auto-Tag Untagged Notes** — AI generates tags for notes missing tags
|
||||
- **Auto-Link Related Notes** — AI inserts "Related Notes" sections with wiki-links
|
||||
|
||||
Both features support:
|
||||
- **Dry-run mode** — preview proposed changes without modifying the vault
|
||||
- **Target folder** — restrict processing to a specific folder and its subfolders
|
||||
- **Tag normalisation** — match generated tags against existing vault vocabulary
|
||||
|
||||
### Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| Open Ollama Chat | Open the chat sidebar |
|
||||
| Clear Semantic Cache | Delete all cached responses |
|
||||
| Clear Vault Index | Delete all indexed vault notes |
|
||||
| Rebuild Vault Index | Rebuild the vault semantic index from scratch |
|
||||
| Auto-Tag Untagged Notes | Run the auto-tagger |
|
||||
| Auto-Link Related Notes | Run the auto-linker |
|
||||
| Clear Structured Memory | Delete all conversation summaries, preferences, and facts |
|
||||
| Clear Tool Telemetry | Delete all recorded telemetry events |
|
||||
|
||||
## Semantic Cache Behaviour
|
||||
|
||||
- The cache is **bypassed** when tool calls are involved (e.g. file creation), since those requests have side effects.
|
||||
@@ -146,11 +214,57 @@ When you send a message, the plugin searches your vault for relevant notes and i
|
||||
- **First paragraph** — 1.5x weight
|
||||
- **General content** — 1x weight
|
||||
|
||||
The plugin also pulls in:
|
||||
- **Explicit mentions** — notes referenced via `[[...]]` wikilinks in the message
|
||||
- **Open note** — the currently active note
|
||||
- **Selected text** — text selected in the active editor
|
||||
- **Backlinks / Outlinks** — notes that link to / from the open note
|
||||
- **Related notes** — semantically similar notes (requires vault semantic index)
|
||||
|
||||
The plugin automatically watches your vault for changes (create, modify, delete, rename) and updates the semantic index in real time when enabled.
|
||||
|
||||
Frontmatter, tags, links, and headings are resolved using Obsidian's built-in `metadataCache` API for accuracy and performance.
|
||||
|
||||
## Tools
|
||||
|
||||
The plugin exposes a `create_file` tool that allows the AI to create new markdown files in your vault. Paths are validated for safety (no `.obsidian`/`.git` access, no path traversal).
|
||||
The assistant has access to a suite of tools that interact with your vault. Available tools depend on the current **Agent Mode**:
|
||||
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `create_note` / `create_file` | Create a new markdown file | Edit |
|
||||
| `read_vault_file` | Read the contents of a note | All |
|
||||
| `search_vault_files` | Keyword-search vault files by path | All |
|
||||
| `append_to_note` | Append text to the end of a note | Edit |
|
||||
| `replace_note_section` | Replace content under a specific heading | Edit |
|
||||
| `update_frontmatter` | Add, update, or remove frontmatter fields | Edit, Organize |
|
||||
| `rename_note` | Rename a note file | Edit, Organize |
|
||||
| `move_note` | Move a note to a different folder | Edit, Organize |
|
||||
| `delete_note` | Delete a note | Edit |
|
||||
| `insert_link` | Insert a `[[wiki-link]]` into a note | Edit, Organize |
|
||||
|
||||
Paths are validated for safety: no `.obsidian`/`.git` access, no path traversal (`..`), no absolute paths, and a 200-character limit.
|
||||
|
||||
## Structured Memory
|
||||
|
||||
When **Enable Structured Memory** is on, the plugin remembers context across sessions by storing three kinds of data in Obsidian's plugin data JSON:
|
||||
|
||||
- **Conversation Summaries** — After each assistant reply, a brief summary (topic + key points) is saved
|
||||
- **User Preferences** — Statements like "I prefer dark mode" or "My favourite colour is blue" are extracted and stored
|
||||
- **Learned Facts** — Simple facts mentioned in conversation (e.g., "Obsidian is a note-taking app") and vault folder paths are remembered
|
||||
|
||||
These are injected as a system message at the start of every LLM call, so the assistant "remembers" context from previous sessions. Limits and clear controls are available in settings.
|
||||
|
||||
## Tool Telemetry
|
||||
|
||||
When **Enable Tool Telemetry** is on, the plugin records:
|
||||
|
||||
- **Tool calls** — which tool, arguments, success/failure, result summary, and duration
|
||||
- **LLM calls** — model, estimated prompt/completion/total tokens, and duration
|
||||
- **Vault searches** — query, number of results, and matched note paths
|
||||
|
||||
Telemetry is stored locally in Obsidian's plugin data. The settings tab shows a **Recent Activity** summary of the last 10 events. Use **Clear Tool Telemetry** to wipe the history.
|
||||
|
||||
> **Note:** Token counts are exact when Ollama provides `prompt_eval_count` and `eval_count` in its response; otherwise they are estimated from character count (÷4 approximation).
|
||||
|
||||
## Supported Models
|
||||
|
||||
@@ -167,9 +281,12 @@ Any Ollama-supported model works. Popular choices:
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
npm test
|
||||
npm test # 520+ unit tests across 21 test suites
|
||||
npm run lint # ESLint check
|
||||
```
|
||||
|
||||
The project uses TypeScript, Jest, and esbuild. Obsidian APIs are mocked in `__mocks__/obsidian.ts` for testing.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
@@ -177,10 +294,13 @@ npm test
|
||||
| Plugin doesn't appear in Obsidian | Install script was not run or failed | Run `./install.sh /path/to/vault` and reload Obsidian |
|
||||
| Cannot connect to Ollama | Ollama is not running | Run `ollama serve` |
|
||||
| Model not found | Model not pulled | Run `ollama pull <model>` |
|
||||
| "Invalid response format" error | Ollama returned a non-JSON response (e.g., proxy error page) | Check that Ollama is healthy at the configured URL |
|
||||
| Semantic cache unavailable (notice shown) | ChromaDB is not running, or the ChromaDB URL is wrong | Start ChromaDB (`chroma run`) and verify the URL in settings |
|
||||
| Cache always misses | Similarity threshold is too high, or the embedding model was changed | Lower the threshold or click **Clear Semantic Cache** and let the cache rebuild |
|
||||
| Slow first response after enabling cache | Embedding model not yet pulled | Run `ollama pull nomic-embed-text` (or the model you configured) |
|
||||
| Permission issues | Vault write permissions | Check that your Obsidian vault has proper write permissions |
|
||||
| Structured memory not showing up | Memory was just cleared or is empty | Have a few conversations — summaries are generated after each assistant reply |
|
||||
| Tool telemetry not recording | Telemetry is disabled or max entries is 0 | Enable **Tool Telemetry** in settings and set **Max Telemetry Entries** > 0 |
|
||||
|
||||
## Security
|
||||
|
||||
|
||||
@@ -701,6 +701,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: `${fullResponse}\n\n*Proposed actions:*\n${writePreviews.map((a) => `- ${a.description}`).join('\n')}`,
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
|
||||
this.render();
|
||||
@@ -749,6 +750,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: finalResponse,
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
|
||||
// Record follow-up LLM call telemetry
|
||||
@@ -761,6 +763,13 @@ export class ChatView extends ItemView {
|
||||
),
|
||||
durationMs: followUpDurationMs,
|
||||
});
|
||||
} else {
|
||||
// No tool results to follow up on — all tools failed or produced no output
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: fullResponse || 'No tool results to report.',
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,6 +818,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: finalResponse,
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
|
||||
// Record follow-up LLM call telemetry
|
||||
@@ -825,6 +835,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: 'Actions applied successfully.',
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -842,6 +853,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(context.assistantMessageId, {
|
||||
content: 'Actions cancelled. No changes were made.',
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -959,6 +971,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: '🔄 Generating workflow plan...',
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
|
||||
const result = await this.workflowEngine.executeWorkflowFromQuery(query, this.getTools());
|
||||
@@ -979,6 +992,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: formatted,
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
|
||||
this.conversationStateManager.updateShortTermContext({
|
||||
@@ -1140,6 +1154,7 @@ export class ChatView extends ItemView {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: fullResponse,
|
||||
isStreaming: false,
|
||||
isThinking: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user