fix: plugin cannot be installed — manifest path, deps, and install script
- manifest.json: fix 'main' from 'src/main.js' to 'dist/main.js' (TypeScript compiles to dist/, not src/ — Obsidian could not find the entry point) - manifest.json: set isDesktopOnly to true (plugin requires a local Ollama server) - package.json: remove unused node-fetch dependency (ESM-only, conflicts with CommonJS build) - src/semantic-cache.ts: use dynamic import for chromadb instead of top-level import (prevents plugin load crash when chromadb is not installed; cache defaults to disabled) - install.sh: new script that installs deps, builds, and copies the plugin into a vault - README.md: add quick install, manual install, and expanded troubleshooting sections
This commit is contained in:
@@ -11,11 +11,6 @@ A plugin that integrates [Ollama](https://ollama.ai) with Obsidian, allowing you
|
|||||||
- Semantic response cache — repeated or similar queries are answered instantly without hitting the model (requires ChromaDB)
|
- Semantic response cache — repeated or similar queries are answered instantly without hitting the model (requires ChromaDB)
|
||||||
- Customisable model, URL, and cache settings
|
- Customisable model, URL, and cache settings
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Install the plugin via Obsidian's community plugins
|
|
||||||
2. Make sure you have Ollama installed and running
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
1. **Install Ollama**: Follow the instructions at [ollama.ai](https://ollama.ai)
|
1. **Install Ollama**: Follow the instructions at [ollama.ai](https://ollama.ai)
|
||||||
@@ -40,14 +35,58 @@ The semantic cache stores responses in a local [ChromaDB](https://www.trychroma.
|
|||||||
```
|
```
|
||||||
4. Enable the cache in the plugin settings and configure the ChromaDB URL.
|
4. Enable the cache in the plugin settings and configure the ChromaDB URL.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Quick install (recommended)
|
||||||
|
|
||||||
|
Use the included install script. It handles dependency installation, building, and copying the plugin into your vault:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone or download this repository, then run:
|
||||||
|
./install.sh /path/to/your/obsidian/vault
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
- Install npm dependencies (excluding Ollama — you install that separately)
|
||||||
|
- Compile the TypeScript plugin
|
||||||
|
- Copy the built plugin into `<vault>/.obsidian/plugins/ollama-plugin/`
|
||||||
|
|
||||||
|
### Manual install
|
||||||
|
|
||||||
|
If you prefer to install manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Then copy the plugin into your vault:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /path/to/vault/.obsidian/plugins/ollama-plugin
|
||||||
|
cp manifest.json /path/to/vault/.obsidian/plugins/ollama-plugin/
|
||||||
|
cp -r dist /path/to/vault/.obsidian/plugins/ollama-plugin/
|
||||||
|
cp -r node_modules/chromadb /path/to/vault/.obsidian/plugins/ollama-plugin/node_modules/ # optional: only needed for semantic cache
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** The `obsidian` npm package is a dev-only type stub — Obsidian provides its own API at runtime. The `chromadb` package is only needed if you enable the semantic cache feature.
|
||||||
|
|
||||||
|
### After installation
|
||||||
|
|
||||||
|
1. Restart Obsidian (or reload: `Ctrl+Shift+P` → "Reload app without saving")
|
||||||
|
2. Go to **Settings → Community plugins** → enable **Ollama Plugin**
|
||||||
|
3. Configure the plugin at **Settings → Ollama Settings**
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Open **Settings → Ollama Chat** to configure the plugin.
|
Open **Settings → Ollama Settings** to configure the plugin.
|
||||||
|
|
||||||
| Setting | Default | Description |
|
| Setting | Default | Description |
|
||||||
|-----|- -- ----|-------|
|
|---------|---------|-------------|
|
||||||
| Ollama URL | `http://localhost:11434` | Base URL of your Ollama instance |
|
| Ollama URL | `http://localhost:11434` | Base URL of your Ollama instance |
|
||||||
| Model | `llama3` | Model used for chat responses |
|
| Model | `llama3` | Model used for chat responses |
|
||||||
|
| Vault Search Limit | `3` | Maximum number of vault entries to include in context |
|
||||||
|
| Max Message History | `50` | Maximum number of messages kept in conversation history |
|
||||||
| Enable Semantic Cache | Off | Cache responses for fast repeated queries |
|
| Enable Semantic Cache | Off | Cache responses for fast repeated queries |
|
||||||
| ChromaDB URL | `http://localhost:8000` | URL of your running ChromaDB instance |
|
| 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 Embedding Model | `nomic-embed-text` | Ollama model used to generate cache embeddings |
|
||||||
@@ -56,7 +95,7 @@ Open **Settings → Ollama Chat** to configure the plugin.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. Click the ribbon icon to open the chat view
|
1. Open the chat view via the command palette (`Ctrl+P` → "Open Ollama Chat") or the ribbon icon
|
||||||
2. Type your message in the input box
|
2. Type your message in the input box
|
||||||
3. Press **Enter** or click **Send** to send your message
|
3. Press **Enter** or click **Send** to send your message
|
||||||
4. Press **Shift+Enter** to insert a line break
|
4. Press **Shift+Enter** to insert a line break
|
||||||
@@ -104,7 +143,8 @@ npm test
|
|||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Symptom | Likely cause | Fix |
|
| Symptom | Likely cause | Fix |
|
||||||
|-----|- -----|---|
|
|---------|-------------|-----|
|
||||||
|
| 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` |
|
| Cannot connect to Ollama | Ollama is not running | Run `ollama serve` |
|
||||||
| Model not found | Model not pulled | Run `ollama pull <model>` |
|
| Model not found | Model not pulled | Run `ollama pull <model>` |
|
||||||
| 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 |
|
| 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 |
|
||||||
|
|||||||
Executable
+133
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# install.sh — Install the Ollama Plugin into an Obsidian vault
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./install.sh /path/to/your/vault
|
||||||
|
#
|
||||||
|
# The script will:
|
||||||
|
# 1. Install npm dependencies (excluding Ollama itself — you need that separately)
|
||||||
|
# 2. Compile the TypeScript plugin
|
||||||
|
# 3. Copy the built plugin into <vault>/.obsidian/plugins/ollama-plugin/
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# - Node.js and npm
|
||||||
|
# - Ollama installed and running (https://ollama.ai)
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Helpers ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
info() { printf "${GREEN}→${NC} %s\n" "$1"; }
|
||||||
|
warn() { printf "${YELLOW}⚠${NC} %s\n" "$1"; }
|
||||||
|
error() { printf "${RED}✗${NC} %s\n" "$1"; }
|
||||||
|
step() { printf "\n${BOLD}══ %s ══${NC}\n" "$1"; }
|
||||||
|
|
||||||
|
# ── Argument validation ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
VAULT_PATH="${1:-}"
|
||||||
|
|
||||||
|
if [ -z "$VAULT_PATH" ]; then
|
||||||
|
echo "Usage: ./install.sh /path/to/your/vault"
|
||||||
|
echo ""
|
||||||
|
echo " Provide the path to your Obsidian vault directory."
|
||||||
|
echo " The plugin will be installed into <vault>/.obsidian/plugins/ollama-plugin/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$VAULT_PATH" ]; then
|
||||||
|
error "Vault directory does not exist: $VAULT_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$VAULT_PATH/.obsidian" ]; then
|
||||||
|
warn "No .obsidian folder found in $VAULT_PATH — this may not be a valid Obsidian vault."
|
||||||
|
warn "Continuing anyway, but the plugin may not load."
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLUGIN_DIR="$VAULT_PATH/.obsidian/plugins/ollama-plugin"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
# ── Check prerequisites ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step "Checking prerequisites"
|
||||||
|
|
||||||
|
if ! command -v node &> /dev/null; then
|
||||||
|
error "Node.js is required but not found. Install it from https://nodejs.org"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "Node.js $(node --version)"
|
||||||
|
|
||||||
|
if ! command -v npm &> /dev/null; then
|
||||||
|
error "npm is required but not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "npm $(npm --version)"
|
||||||
|
|
||||||
|
# ── Install dependencies ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step "Installing npm dependencies"
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
npm install --production
|
||||||
|
info "Dependencies installed"
|
||||||
|
|
||||||
|
# ── Build ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step "Building the plugin"
|
||||||
|
|
||||||
|
npm run build
|
||||||
|
info "Build complete"
|
||||||
|
|
||||||
|
# ── Install into vault ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step "Installing into vault"
|
||||||
|
|
||||||
|
mkdir -p "$PLUGIN_DIR"
|
||||||
|
|
||||||
|
# Copy manifest and built output
|
||||||
|
cp "$SCRIPT_DIR/manifest.json" "$PLUGIN_DIR/"
|
||||||
|
cp -r "$SCRIPT_DIR/dist" "$PLUGIN_DIR/"
|
||||||
|
|
||||||
|
# Copy only necessary runtime dependencies (obsidian and chromadb stubs)
|
||||||
|
# The obsidian package is only used for type definitions at build time —
|
||||||
|
# at runtime Obsidian provides its own API, so we don't need it in node_modules.
|
||||||
|
# chromadb is loaded dynamically and only needed when the cache is enabled.
|
||||||
|
mkdir -p "$PLUGIN_DIR/node_modules"
|
||||||
|
if [ -d "$SCRIPT_DIR/node_modules/chromadb" ]; then
|
||||||
|
cp -r "$SCRIPT_DIR/node_modules/chromadb" "$PLUGIN_DIR/node_modules/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Plugin installed to $PLUGIN_DIR"
|
||||||
|
|
||||||
|
# ── Verify ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
step "Verifying installation"
|
||||||
|
|
||||||
|
if [ -f "$PLUGIN_DIR/manifest.json" ] && [ -f "$PLUGIN_DIR/dist/main.js" ]; then
|
||||||
|
info "manifest.json ✓"
|
||||||
|
info "dist/main.js ✓"
|
||||||
|
else
|
||||||
|
error "Installation verification failed — missing files in $PLUGIN_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " ${GREEN}${BOLD}Done!${NC} The plugin has been installed."
|
||||||
|
echo ""
|
||||||
|
echo " Next steps:"
|
||||||
|
echo " 1. Restart Obsidian (or reload plugins: Ctrl+Shift+P → 'Reload app without saving')"
|
||||||
|
echo " 2. Go to Settings → Community plugins → enable 'Ollama Plugin'"
|
||||||
|
echo " 3. Configure the plugin: Settings → Ollama Settings"
|
||||||
|
echo ""
|
||||||
|
echo " Make sure Ollama is running:"
|
||||||
|
echo " ollama serve"
|
||||||
|
echo " ollama pull llama3 (or your preferred model)"
|
||||||
|
echo ""
|
||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"description": "Ollama integration plugin for Obsidian",
|
"description": "Ollama integration plugin for Obsidian",
|
||||||
"author": "Anonymous",
|
"author": "Anonymous",
|
||||||
"authorUrl": "",
|
"authorUrl": "",
|
||||||
"isDesktopOnly": false,
|
"isDesktopOnly": true,
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
"authorization": [],
|
"authorization": [],
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chromadb": "^1.5.3",
|
"chromadb": "^1.5.3",
|
||||||
"node-fetch": "^3.3.2",
|
|
||||||
"obsidian": "^1.4.11"
|
"obsidian": "^1.4.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-11
@@ -1,13 +1,11 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
|
|
||||||
/* eslint-disable */
|
|
||||||
// src/semantic-cache.ts
|
// src/semantic-cache.ts
|
||||||
|
|
||||||
import { ChromaClient } from 'chromadb';
|
|
||||||
import { Logger } from './utils';
|
import { Logger } from './utils';
|
||||||
import { CacheConfig } from './types';
|
import { CacheConfig } from './types';
|
||||||
|
|
||||||
export class SemanticCacheService {
|
export class SemanticCacheService {
|
||||||
private client: ChromaClient;
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
private client: any | null = null;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
private collection: any | null = null;
|
private collection: any | null = null;
|
||||||
private config: CacheConfig;
|
private config: CacheConfig;
|
||||||
@@ -16,15 +14,17 @@ export class SemanticCacheService {
|
|||||||
constructor(ollamaURL: string, config: CacheConfig) {
|
constructor(ollamaURL: string, config: CacheConfig) {
|
||||||
this.ollamaURL = ollamaURL.replace(/\/+$/, '');
|
this.ollamaURL = ollamaURL.replace(/\/+$/, '');
|
||||||
this.config = config;
|
this.config = config;
|
||||||
// Use configurable ChromaDB URL or default to localhost
|
|
||||||
const chromaURL = config.chromaURL || 'http://localhost:8000';
|
|
||||||
this.client = new ChromaClient({ path: chromaURL });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
if (!this.config.enabled) return;
|
if (!this.config.enabled) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Dynamic import — chromadb is optional and may not be installed.
|
||||||
|
// This prevents the plugin from crashing at load time if chromadb is absent.
|
||||||
|
const { ChromaClient } = await import('chromadb');
|
||||||
|
const chromaURL = this.config.chromaURL || 'http://localhost:8000';
|
||||||
|
this.client = new ChromaClient({ path: chromaURL });
|
||||||
this.collection = await this.client.getOrCreateCollection({
|
this.collection = await this.client.getOrCreateCollection({
|
||||||
name: this.config.collectionName,
|
name: this.config.collectionName,
|
||||||
metadata: { 'hnsw:space': 'cosine' },
|
metadata: { 'hnsw:space': 'cosine' },
|
||||||
@@ -49,11 +49,8 @@ export class SemanticCacheService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (results.ids[0] && results.ids[0].length > 0) {
|
if (results.ids[0] && results.ids[0].length > 0) {
|
||||||
const [id] = results.ids[0];
|
|
||||||
const [content] = results.documents[0];
|
|
||||||
|
|
||||||
if (results.distances[0] && results.distances[0][0] > this.config.similarityThreshold) {
|
if (results.distances[0] && results.distances[0][0] > this.config.similarityThreshold) {
|
||||||
return content;
|
return results.documents[0][0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user