mirror of
https://github.com/open-webui/oikb.git
synced 2026-07-09 16:00:53 +00:00
0.2.3: remove routes, simplify config to one entry = one KB
Drop the ambiguous 'routes' key from .oikb.yaml. Multi-KB from a single source is now done with multiple entries + filter.include. Every entry is strictly source + kb-id, no branching logic.
This commit is contained in:
parent
3c8edaf93f
commit
7c3d36f1b5
6 changed files with 53 additions and 71 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.2.3] - 2025-05-21
|
||||
|
||||
### Removed
|
||||
|
||||
- **Breaking:** `routes` key in `.oikb.yaml`. Use multiple entries with `filter.include` instead — each entry is one source → one KB.
|
||||
|
||||
## [0.2.2] - 2025-05-21
|
||||
|
||||
### Added
|
||||
|
|
@ -35,7 +41,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||
- Webhook support: /webhooks/github, /webhooks/gitlab, /webhooks/slack, /webhooks/confluence for real-time sync triggers.
|
||||
- `--json` output flag for `history` command.
|
||||
- 13 new connectors: Document360, Slab, Outline, Google Sites, Egnyte, Oracle Cloud Storage, ProductBoard, XenForo, Zulip, Gong, Fireflies, DokuWiki, ServiceNow. Total: 44 connectors.
|
||||
- Multi-KB routing: `routes` key in `.oikb.yaml` to route files by glob pattern to different KBs.
|
||||
- Selective sync filters: `filter.include` / `filter.exclude` glob patterns to narrow sync scope.
|
||||
- Daemon doubles as an OpenAPI tool server for Open WebUI (Settings → Connections → Tool Server).
|
||||
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -124,21 +124,7 @@ oikb sync servicenow:incident --kb-id your-kb-id
|
|||
|
||||
Some connectors need an optional extra: `pip install oikb[gdrive]`, `pip install oikb[s3]`, or `pip install oikb[all]` for everything.
|
||||
|
||||
## Multi-KB Routing
|
||||
|
||||
Route files from a single source to different Knowledge Bases by glob pattern:
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
- name: wiki
|
||||
source: github:owner/repo
|
||||
kb-id: 8f3a2b1c-...
|
||||
routes:
|
||||
"docs/**/*.md": docs-kb-id
|
||||
"src/**": code-kb-id
|
||||
```
|
||||
|
||||
## Selective Sync Filters
|
||||
## Filters
|
||||
|
||||
Narrow what gets synced with include/exclude globs:
|
||||
|
||||
|
|
@ -152,6 +138,23 @@ sources:
|
|||
exclude: ["drafts/**"]
|
||||
```
|
||||
|
||||
To split a single source across multiple Knowledge Bases, use separate entries:
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
- name: wiki-docs
|
||||
source: github:owner/repo
|
||||
kb-id: abc123-...
|
||||
filter:
|
||||
include: ["docs/**/*.md"]
|
||||
|
||||
- name: wiki-code
|
||||
source: github:owner/repo
|
||||
kb-id: def456-...
|
||||
filter:
|
||||
include: ["src/**"]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Resolved in order (highest priority wins):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "oikb"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
description = "Sync anything to Open WebUI Knowledge Bases"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
"""oikb — Open WebUI Knowledge Base CLI."""
|
||||
|
||||
__version__ = "0.2.0"
|
||||
__version__ = "0.2.3"
|
||||
|
|
|
|||
|
|
@ -344,70 +344,44 @@ def sync(
|
|||
entry_kb = entry.get("kb-id")
|
||||
entry_branch = entry.get("branch")
|
||||
entry_path = entry.get("path")
|
||||
entry_routes = entry.get("routes")
|
||||
entry_filter = entry.get("filter", {})
|
||||
|
||||
if not entry_source or (not entry_kb and not entry_routes):
|
||||
click.echo(click.style(f"Skipping invalid entry (needs source + kb-id or routes): {entry}", fg="yellow"), err=True)
|
||||
if not entry_source or not entry_kb:
|
||||
click.echo(click.style(f"Skipping invalid entry (needs source + kb-id): {entry}", fg="yellow"), err=True)
|
||||
continue
|
||||
|
||||
try:
|
||||
connector = _resolve_connector(entry_source, entry_branch, entry_path)
|
||||
client = _make_client(url, token)
|
||||
|
||||
# ── Multi-KB routing mode ──
|
||||
if entry_routes:
|
||||
if not quiet:
|
||||
click.echo(f"\n{'─' * 40}")
|
||||
click.echo(f"Syncing: {entry_source} → {entry_kb}")
|
||||
|
||||
mf = None
|
||||
if entry_filter.get("include") or entry_filter.get("exclude"):
|
||||
from oikb.sync import build_manifest_filter
|
||||
for pattern, route_kb in entry_routes.items():
|
||||
if not quiet:
|
||||
click.echo(f"\n{'─' * 40}")
|
||||
click.echo(f"Syncing: {entry_source} [{pattern}] → {route_kb}")
|
||||
mf = build_manifest_filter(include=[pattern])
|
||||
result = run_sync(
|
||||
client=client,
|
||||
connector=connector,
|
||||
kb_id=route_kb,
|
||||
dry_run=dry_run,
|
||||
verbose=verbose,
|
||||
quiet=quiet,
|
||||
manifest_filter=mf,
|
||||
)
|
||||
if not quiet:
|
||||
prefix = "Dry run" if dry_run else "Done"
|
||||
click.echo(f" {prefix}: {result.summary()}")
|
||||
if result.errors:
|
||||
has_errors = True
|
||||
|
||||
# ── Standard single-KB mode ──
|
||||
else:
|
||||
if not quiet:
|
||||
click.echo(f"\n{'─' * 40}")
|
||||
click.echo(f"Syncing: {entry_source} → {entry_kb}")
|
||||
|
||||
mf = None
|
||||
if entry_filter.get("include") or entry_filter.get("exclude"):
|
||||
from oikb.sync import build_manifest_filter
|
||||
mf = build_manifest_filter(
|
||||
include=entry_filter.get("include"),
|
||||
exclude=entry_filter.get("exclude"),
|
||||
)
|
||||
|
||||
result = run_sync(
|
||||
client=client,
|
||||
connector=connector,
|
||||
kb_id=entry_kb,
|
||||
dry_run=dry_run,
|
||||
verbose=verbose,
|
||||
quiet=quiet,
|
||||
manifest_filter=mf,
|
||||
mf = build_manifest_filter(
|
||||
include=entry_filter.get("include"),
|
||||
exclude=entry_filter.get("exclude"),
|
||||
)
|
||||
|
||||
if not quiet:
|
||||
prefix = "Dry run" if dry_run else "Done"
|
||||
click.echo(f" {prefix}: {result.summary()}")
|
||||
result = run_sync(
|
||||
client=client,
|
||||
connector=connector,
|
||||
kb_id=entry_kb,
|
||||
dry_run=dry_run,
|
||||
verbose=verbose,
|
||||
quiet=quiet,
|
||||
manifest_filter=mf,
|
||||
)
|
||||
|
||||
if result.errors:
|
||||
has_errors = True
|
||||
if not quiet:
|
||||
prefix = "Dry run" if dry_run else "Done"
|
||||
click.echo(f" {prefix}: {result.summary()}")
|
||||
|
||||
if result.errors:
|
||||
has_errors = True
|
||||
|
||||
client.close()
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,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.2.2",
|
||||
version="0.2.3",
|
||||
)
|
||||
|
||||
# Runtime state populated by start_daemon().
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue