mirror of
https://github.com/open-webui/oikb.git
synced 2026-07-09 16:00:53 +00:00
0.3.2: global defaults key, Docker usage docs
defaults: key in .oikb.yaml sets interval, concurrency, filter, notify, etc. once for all entries — per-entry values override. Deep merges nested dicts. Added standalone docker run example and LOG_FORMAT=json to Docker Compose.
This commit is contained in:
parent
4e047b3307
commit
878e797b5f
6 changed files with 56 additions and 9 deletions
|
|
@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## [0.3.2] - 2025-05-21
|
||||
|
||||
### Added
|
||||
|
||||
- Global `defaults:` key in `.oikb.yaml` — set `interval`, `concurrency`, `filter`, `notify`, or any other key once and have it apply to all entries. Per-entry values override defaults. Deep merges nested dicts (filter, notify).
|
||||
|
||||
## [0.3.1] - 2025-05-21
|
||||
|
||||
### Added
|
||||
|
|
|
|||
29
README.md
29
README.md
|
|
@ -56,20 +56,25 @@ Features:
|
|||
|
||||
```yaml
|
||||
# .oikb.yaml
|
||||
defaults:
|
||||
interval: 1h
|
||||
concurrency: 4
|
||||
filter:
|
||||
max-size: 50mb
|
||||
notify:
|
||||
url: https://hooks.slack.com/services/T.../B.../xxx
|
||||
on: error
|
||||
|
||||
sources:
|
||||
- name: wiki
|
||||
source: github:owner/repo
|
||||
kb-id: 8f3a2b1c-...
|
||||
interval: 1h # simple interval
|
||||
webhook: true
|
||||
notify:
|
||||
url: https://hooks.slack.com/services/T.../B.../xxx
|
||||
on: error # error (default) | always
|
||||
|
||||
- name: handbook
|
||||
source: confluence:ENG
|
||||
kb-id: 4e7d9a0f-...
|
||||
interval: "0 6 * * 1-5" # cron: weekdays at 6am
|
||||
interval: "0 6 * * 1-5" # overrides default
|
||||
```
|
||||
|
||||
```bash
|
||||
|
|
@ -78,6 +83,19 @@ curl -X POST /sync/wiki # API: trigger by name
|
|||
curl -X POST /sync/8f3a2b1c-.. # API: trigger by kb-id
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-e OPEN_WEBUI_URL=http://open-webui:8080 \
|
||||
-e OPEN_WEBUI_API_KEY=sk-... \
|
||||
-e OIKB_API_KEY=your-daemon-key \
|
||||
-e LOG_FORMAT=json \
|
||||
-v ./.oikb.yaml:/app/.oikb.yaml:ro \
|
||||
-p 8080:8080 \
|
||||
ghcr.io/open-webui/oikb:latest daemon
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
|
|
@ -93,6 +111,7 @@ services:
|
|||
- OPEN_WEBUI_URL=http://open-webui:8080
|
||||
- OPEN_WEBUI_API_KEY=${OPEN_WEBUI_API_KEY}
|
||||
- OIKB_API_KEY=${OIKB_API_KEY}
|
||||
- LOG_FORMAT=json
|
||||
volumes:
|
||||
- ./.oikb.yaml:/app/.oikb.yaml:ro
|
||||
command: daemon
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "oikb"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
description = "Sync anything to Open WebUI Knowledge Bases"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
"""oikb — Open WebUI Knowledge Base CLI."""
|
||||
|
||||
__version__ = "0.3.1"
|
||||
__version__ = "0.3.2"
|
||||
|
|
|
|||
|
|
@ -295,6 +295,17 @@ def _interpolate_env(obj: Any) -> Any:
|
|||
return obj
|
||||
|
||||
|
||||
def _deep_merge(base: dict, override: dict) -> dict:
|
||||
"""Deep merge two dicts. Values in override take precedence."""
|
||||
result = base.copy()
|
||||
for key, val in override.items():
|
||||
if key in result and isinstance(result[key], dict) and isinstance(val, dict):
|
||||
result[key] = _deep_merge(result[key], val)
|
||||
else:
|
||||
result[key] = val
|
||||
return result
|
||||
|
||||
|
||||
def _load_oikb_yaml() -> list[dict] | None:
|
||||
"""Load .oikb.yaml from the current directory if it exists."""
|
||||
import yaml
|
||||
|
|
@ -314,7 +325,15 @@ def _load_oikb_yaml() -> list[dict] | None:
|
|||
|
||||
# Prefer sources: (new), fall back to sync: (legacy).
|
||||
entries = data.get("sources") or data.get("sync")
|
||||
return entries or None
|
||||
if not entries:
|
||||
return None
|
||||
|
||||
# Apply global defaults to each entry.
|
||||
defaults = data.get("defaults", {})
|
||||
if defaults:
|
||||
entries = [_deep_merge(defaults, entry) for entry in entries]
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def _build_cli_filter(max_file_size: str | None):
|
||||
|
|
@ -817,6 +836,9 @@ def daemon(port: int, no_server: bool, config_file: str | None, log_format: str
|
|||
data = yaml.safe_load(f)
|
||||
data = _interpolate_env(data) if data else data
|
||||
entries = (data.get("sources") or data.get("sync", [])) if data else []
|
||||
defaults = data.get("defaults", {}) if data else {}
|
||||
if defaults and entries:
|
||||
entries = [_deep_merge(defaults, e) for e in entries]
|
||||
else:
|
||||
entries = _load_oikb_yaml()
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ async def verify_api_key(
|
|||
app = FastAPI(
|
||||
title="oikb",
|
||||
description="Sync engine for Open WebUI Knowledge Bases. Trigger syncs, check status, and query history.",
|
||||
version="0.3.1",
|
||||
version="0.3.2",
|
||||
)
|
||||
|
||||
# Runtime state populated by start_daemon().
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue