Commit Graph

170 Commits

Author SHA1 Message Date
8ccaaf28c8 docs: update README for client/daemon package split
- Separate package tables for core, plugins, and meta bundles
- Add owlry-plugin-converter to plugin list and meta-essentials
- Fix build instructions: plugins are in owlry-plugins repo
- Update plugin count to 14
- Remove dead link to gitignored CLAUDE.md
2026-03-28 09:51:29 +01:00
cfd143fe4a chore: track AUR package files (PKGBUILD, .SRCINFO)
The aur/ directory was entirely gitignored, preventing PKGBUILD and
.SRCINFO files from being tracked. Fix .gitignore to only ignore
build artifacts and nested .git dirs, matching the owlry-plugins
repo convention.
2026-03-28 09:34:21 +01:00
10a685c62f chore(owlry): bump version to 1.0.2 owlry-core-v1.1.1 owlry-v1.0.2 2026-03-28 09:16:40 +01:00
34db33c75f chore(owlry-core): bump version to 1.1.1 2026-03-28 09:16:38 +01:00
4bff83b5e6 perf(ui): eliminate redundant results.clone() in search handlers
The full results Vec was cloned into lazy_state.all_results and then
separately consumed for current_results. Now we slice for current_results
and move the original into lazy_state, avoiding one full Vec allocation
per query.
2026-03-28 09:14:11 +01:00
8f7501038d perf(ui): move search IPC off the GTK main thread
Search queries in daemon mode now run on a background thread via
DaemonHandle::query_async(). Results are posted back to the main
thread via glib::spawn_future_local + futures_channel::oneshot.
The GTK event loop is never blocked by IPC, eliminating perceived
input lag.

Local mode (dmenu) continues to use synchronous search since it
has no IPC overhead.
2026-03-28 09:12:20 +01:00
4032205800 perf(ui): defer initial query to after window.present()
update_results('') was called inside MainWindow::new(), blocking the
window from appearing until the daemon responded. Move it to a
glib::idle_add_local_once callback scheduled after present() so the
window renders immediately.
2026-03-28 08:51:33 +01:00
99985c7f3b perf(ui): use tracked count in scroll_to_row instead of child walk
scroll_to_row walked all GTK children via first_child/next_sibling
to count rows. The count is already available in LazyLoadState, so
use that directly. Eliminates O(n) widget traversal per arrow key.
2026-03-28 08:48:52 +01:00
6113217f7b perf(core): sample Utc::now() once per search instead of per-item
get_score() called Utc::now() inside calculate_frecency() for every
item in the search loop. Added get_score_at() that accepts a pre-sampled
timestamp. Eliminates hundreds of unnecessary clock_gettime syscalls
per keystroke.
2026-03-28 08:45:21 +01:00
558d415e12 perf(config): replace which subprocesses with in-process PATH scan
detect_terminal() was spawning up to 17 'which' subprocesses sequentially
on every startup. Replace with std::env::split_paths + is_file() check.
Eliminates 200-500ms of fork+exec overhead on cold cache.
2026-03-28 08:40:22 +01:00
6bde1504b1 chore: add .worktrees/ to gitignore 2026-03-28 08:35:51 +01:00
ffe04f3c54 docs: add per-crate tagging convention to CLAUDE.md owlry-core-v1.1.0 owlry-lua-v1.1.0 owlry-rune-v1.1.0 owlry-v1.0.1 plugin-api-v1.0.1 2026-03-26 18:57:09 +01:00
5c0e63f94c chore(owlry-rune): bump version to 1.1.0 2026-03-26 18:51:20 +01:00
5441011d6b chore(owlry-lua): bump version to 1.1.0 2026-03-26 18:51:20 +01:00
317572634f chore(owlry): bump version to 1.0.1 2026-03-26 18:51:12 +01:00
449dc010db chore(owlry-core): bump version to 1.1.0 2026-03-26 18:51:04 +01:00
7273cd3ba7 chore(owlry-plugin-api): bump version to 1.0.1 2026-03-26 18:50:58 +01:00
f8388a4327 docs: update CLAUDE.md with script runtime loading, hot-reload, dynamic prefixes 2026-03-26 18:47:05 +01:00
fa671ebd77 feat: dynamic prefix fallback for user plugin prefixes (e.g. :hs for hyprshutdown) 2026-03-26 18:40:23 +01:00
d63c7d170b fix: build Rune provider registrations from manifest [[providers]] declarations 2026-03-26 18:37:33 +01:00
5f14ed2b3b fix: register Rune Item type under owlry crate path 2026-03-26 18:35:41 +01:00
83f551dd7f fix: use rune::function attribute for Item constructor and builder methods 2026-03-26 18:30:39 +01:00
9b1eada1ee fix: set accept_all when no CLI mode restriction so user plugins appear in default filter 2026-03-26 18:27:50 +01:00
677e6d7fa9 fix: send accept_all filter as None in IPC so runtime plugins appear in results 2026-03-26 18:21:32 +01:00
f0741f4128 fix: store Lua provider callbacks for refresh, fix Rune Item::new parameter types 2026-03-26 18:12:07 +01:00
7da8f3c249 fix: align Lua ProviderInfo ABI, implement Rune Item type and refresh/query 2026-03-26 18:07:46 +01:00
38dda8c44c fix: watcher startup grace period, defensive runtime drop on reload 2026-03-26 17:59:32 +01:00
ab2d3cfe55 feat: add filesystem watcher for automatic user plugin hot-reload
Watch ~/.config/owlry/plugins/ for changes using notify-debouncer-mini
(500ms debounce) and trigger a full runtime reload on file modifications.
Respects OWLRY_SKIP_RUNTIMES=1 to skip watcher in tests.
2026-03-26 17:48:15 +01:00
e2939e266c feat: wire script runtime loading into daemon ProviderManager 2026-03-26 17:44:33 +01:00
651166a9f3 feat: change default entry points to main.lua/main.rn, add entry_point alias 2026-03-26 17:33:54 +01:00
a2eb7d1b0d fix: align runtime ABI — shrink Lua RuntimeInfo, pass owlry_version to init
- Shrink Lua RuntimeInfo from 5 fields to 2 (name, version), matching
  core and Rune. The mismatch caused SIGSEGV across the ABI boundary.
- Add owlry_version parameter to vtable init in all three crates
  (core, Lua, Rune) so runtimes receive the version at init time
  instead of hardcoding it.
- Remove unused Lua constants (RUNTIME_ID, RUNTIME_NAME, etc.) and
  LUA_RUNTIME_API_VERSION.
- Update plugin_commands.rs call sites to pass CARGO_PKG_VERSION.
2026-03-26 17:31:23 +01:00
8073d27df2 docs: update LuaProvider safety comment for RwLock architecture 2026-03-26 16:51:55 +01:00
3349350bf6 fix: robustness — RwLock for concurrent reads, log malformed JSON requests
Replace Mutex with RwLock for ProviderManager and FrecencyStore in the
IPC server. Most request types (Query, Providers, Submenu, PluginAction)
only need read access and can now proceed concurrently. Only Launch
(frecency write) and Refresh (provider write) acquire exclusive locks.

Also adds a warn!() log for malformed JSON requests before sending the
error response, improving observability for debugging client issues.

Provider trait now requires Send + Sync to satisfy RwLock's Sync bound
on the inner type. RuntimeProvider and LuaProvider gain the
corresponding unsafe impl Sync.
2026-03-26 16:39:10 +01:00
3aaeafde8b fix: security — socket perms 0600, signal handler logging, client read timeout 2026-03-26 16:32:06 +01:00
7ce6de17aa fix: soundness — OnceLock for HOST_API, IPC size limits, mutex poisoning recovery 2026-03-26 16:29:47 +01:00
91da177f46 feat: architecture split — client/daemon with independent plugin repo owlry-core-v1.0.0 owlry-lua-v1.0.0 owlry-rune-v1.0.0 owlry-v1.0.0 plugin-api-v1.0.0 2026-03-26 13:40:24 +01:00
f5d83f1372 chore: format, fix clippy warnings, bump all crates to 1.0.0 2026-03-26 13:37:55 +01:00
50caa1ff0d fix(owlry-core): make ProviderFilter dynamically accept all plugin types
Replace hardcoded list of 13 plugin IDs in ProviderFilter::all() with
an accept_all flag. When set, is_active()/is_enabled() return true for
any ProviderType, so dynamically loaded plugins are accepted without
maintaining a static list. Prefix-based filtering still narrows scope
as before, and from_mode_strings() still filters to explicit modes only.
2026-03-26 13:30:51 +01:00
0c46082b2b docs: update CLAUDE.md for client/daemon architecture 2026-03-26 13:27:45 +01:00
a0b65e69a4 refactor: remove plugin crates from core repo
Plugins have been moved to the owlry-plugins repo. This removes:
- All 13 owlry-plugin-* crate directories
- Plugin documentation (PLUGINS.md, PLUGIN_DEVELOPMENT.md)
- Plugin-specific justfile targets (build, bump, AUR)

Retained in core: owlry (UI), owlry-core (daemon),
owlry-plugin-api (ABI interface), owlry-lua, owlry-rune (runtimes).
2026-03-26 13:21:59 +01:00
938a9ee6f3 docs: update README and justfile for client/daemon architecture 2026-03-26 13:03:48 +01:00
d4f71cae42 feat: add systemd user service and socket units for owlry-core
Add owlry-core.service (Type=simple, restart-on-failure) and
owlry-core.socket (listening on $XDG_RUNTIME_DIR/owlry/owlry.sock)
for socket-activated daemon deployment.
2026-03-26 12:59:49 +01:00
6391711df2 feat: add config profiles, remove --providers flag
Add ProfileConfig struct and profiles map to Config, allowing named
mode presets in config.toml (e.g. [profiles.dev] modes = ["app","cmd"]).

Remove the --providers/-p CLI flag and repurpose -p as the short form
for --prompt. Add --profile flag that loads modes from a named profile.

Mode resolution priority: --mode > --profile > config defaults.
2026-03-26 12:58:47 +01:00
30b2b5b9c0 feat(owlry): implement toggle behavior for repeated invocations
Use a flock-based lock file at $XDG_RUNTIME_DIR/owlry/owlry-ui.lock
to detect when another owlry UI instance is already running. If the
lock is held, send a Toggle IPC command to the daemon and exit
immediately instead of opening a second window.
2026-03-26 12:56:30 +01:00
5be21aadc6 refactor(owlry): wire UI to use IPC client instead of direct provider calls
The UI now uses a SearchBackend abstraction that wraps either:
- CoreClient (daemon mode): connects to owlry-core via IPC for search,
  frecency tracking, submenu queries, and plugin actions
- Local ProviderManager (dmenu mode): unchanged direct provider access

Key changes:
- New backend.rs with SearchBackend enum abstracting IPC vs local
- app.rs creates CoreClient in normal mode, falls back to local if
  daemon unavailable
- main_window.rs uses SearchBackend instead of ProviderManager+FrecencyStore
- Command execution stays in the UI (daemon only tracks frecency)
- dmenu mode path is completely unchanged (no daemon involvement)
- Added terminal field to IPC ResultItem for proper terminal launch
- Added PluginAction IPC request for plugin command execution
2026-03-26 12:52:00 +01:00
4ed9a9973a feat(owlry): implement IPC client for daemon communication
Add CoreClient struct that connects to the owlry-core daemon Unix socket
and provides typed methods for query, launch, providers, toggle, and
submenu operations. Reuses owlry_core::paths::socket_path() as the
single source of truth for the socket location. Includes connect_or_start()
with systemd integration and exponential backoff retry logic.
2026-03-26 12:33:27 +01:00
18c58ce33d feat(owlry-core): add daemon binary entry point
Add [[bin]] target and main.rs that starts the IPC server with
env_logger, socket path from XDG_RUNTIME_DIR, and graceful shutdown
via ctrlc signal handler. Also add socket_path() to paths module.
2026-03-26 12:28:53 +01:00
f609ce1c13 feat(owlry-core): implement IPC server over Unix socket
Adds Server struct that listens on a Unix domain socket, accepts
client connections (thread-per-client), reads newline-delimited JSON
requests, dispatches to ProviderManager/FrecencyStore/Config, and
sends JSON responses back. Includes stale socket cleanup and Drop
impl for socket removal.
2026-03-26 12:26:06 +01:00
915dc193d9 feat(owlry-core): add daemon-friendly API to ProviderManager and ProviderFilter
Add methods needed by the IPC server (Task 9) to create filters from
mode strings, query provider metadata, and refresh individual providers.

ProviderFilter:
- from_mode_strings(): create filter from ["app", "cmd", "calc"] etc.
- all(): create permissive filter accepting all provider types
- mode_string_to_provider_type(): public helper for string-to-type mapping

ProviderManager:
- ProviderDescriptor struct for IPC provider metadata responses
- available_providers() -> Vec<ProviderDescriptor> (replaces ProviderType version)
- refresh_provider(id): refresh a single provider by type_id
- new_with_config(config): self-contained init for daemon use

NativeProvider:
- icon(): get provider's default icon name
- position_str(): get position as "normal"/"widget" string
2026-03-26 12:22:37 +01:00
71d78ce7df feat(owlry-core): define IPC message types with serde 2026-03-26 12:17:16 +01:00