From ff4db30d1f1e8b00aaea3c93b5952f327a250eff Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:20:32 +0200 Subject: [PATCH 1/6] release: prepare v0.21.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bump workspace version 0.20.2 → 0.21.0 - Finalize CHANGELOG.md [0.21.0] section with consolidated headers - Update TUI splash snapshot for new version - Update README: tests badge (9139), docs links, new features - Update crate READMEs: zeph-channels, zeph-memory, zeph-core - Update book docs: Telegram Guest Mode, BeliefMem, ShadowSentinel, hooks - Add new book pages: cocoon.md, shadow-sentinel.md - Update specs: channels 007, hooks 028, security 050, APEX-MEM 004-7 --- CHANGELOG.md | 81 +++--- Cargo.lock | 60 ++--- Cargo.toml | 60 ++--- README.md | 11 +- book/src/SUMMARY.md | 2 + book/src/advanced/tui.md | 104 +++++++- book/src/concepts/graph-memory.md | 64 +++++ book/src/concepts/hooks.md | 80 +++++- book/src/guides/cocoon.md | 231 ++++++++++++++++++ book/src/guides/telegram.md | 74 +++++- .../src/reference/security/shadow-sentinel.md | 168 +++++++++++++ crates/zeph-channels/README.md | 29 ++- crates/zeph-core/README.md | 33 +++ crates/zeph-memory/README.md | 16 ++ ...idgets__splash__tests__splash_default.snap | 3 +- specs/004-memory/004-7-memory-apex-magma.md | 18 +- .../007-channels/007-1-telegram-guest-mode.md | 26 +- .../007-channels/007-2-telegram-bot-to-bot.md | 26 +- specs/007-channels/spec.md | 33 +++ specs/028-hooks/spec.md | 11 + .../spec.md | 37 ++- specs/README.md | 8 +- 22 files changed, 1013 insertions(+), 162 deletions(-) create mode 100644 book/src/guides/cocoon.md create mode 100644 book/src/reference/security/shadow-sentinel.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f6e2c669..d6e3d4e9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] -### Fixed - -- fix(security): wire `ShadowProbeExecutor` into the agent executor chain (`src/runner.rs`). - `ShadowSentinel` is now instantiated when `security.shadow_sentinel.enabled = true` and - inserted between `ScopedToolExecutor` and `PolicyGateExecutor` as required by spec 050 §Phase 2. - Adds `ShadowSentinelProbeGateAdapter` bridge to avoid circular crate dependency. Wires - `sentinel.advance_turn()` into `begin_turn()`. Closes #3739. +## [0.21.0] - 2026-05-11 ### Added @@ -27,7 +21,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Bot token is redacted in `Debug` output and stripped from `reqwest` errors via `.without_url()`. Unblocks Guest Mode (#3729), Bot-to-Bot communication (#3730), and reaction moderation (#3731). Closes #3728. - - feat(channels): add Telegram Guest Mode and Bot-to-Bot communication (`zeph-channels`, `zeph-config`). Guest Mode spawns a transparent local axum HTTP proxy on an ephemeral port that intercepts `getUpdates` responses from `api.telegram.org`, extracts `guest_message` entries (which @@ -43,7 +36,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `ChannelMessage.is_guest_context` → `SessionState.is_guest_context` → volatile system prompt annotation. Fixed missing `is_guest_context`/`is_from_bot` fields in `gateway_spawn.rs` and `daemon.rs`. Closes #3729, #3730. - - feat(memory): add BeliefMem probabilistic edge layer to APEX-MEM (`zeph-memory`). New `pending_beliefs` + `belief_evidence` SQLite tables (migration 084) store candidate facts with probability weights before commitment. Evidence accumulates via Noisy-OR with optional temporal @@ -73,33 +65,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `● Explored N files` / `● Ran N commands` with a collapsible sub-list of primary args (capped at 8 in Inline density, unlimited in Block, hidden in Compact). Groups break on role change, streaming tool, or different `ToolKind`. Closes #3719. (#3724) - -### Fixed - -- fix(hooks): `pre_tool_use` hooks now fire for tool calls intercepted by the utility gate; - previously the hook block was skipped because `check_call_gates` returned early with `continue`. - Closes #3738. -- fix(tui): parallel tool call output no longer gets cross-contaminated in the TUI. `tool_call_id` - is now threaded from `ToolCall` through `ShellExecutor` → `ToolEvent::OutputChunk` → - `tui_bridge` → `AgentEvent::ToolOutputChunk/ToolStart/ToolOutput`. The TUI uses id-based - lookup when `tool_call_id` is non-empty; on miss it drops the chunk with a `warn!` log - instead of falling back to the last streaming message (which was the source of the bug). - The legacy empty-id path retains the old `rposition` fallback for backwards compatibility. - Closes #3688. (#3708) -- fix(tui): `handle_diff_ready` now correlates diffs to tool messages by `tool_call_id` instead of - a position-based `.rev().find()` scan, preventing diffs from attaching to the wrong message when - multiple tool calls are in flight. `AgentEvent::DiffReady` is now a struct variant carrying - `tool_call_id: String`. `ToolOutputChunk` lookup similarly uses id-based matching with a fallback - to the last streaming Tool message for shell tools whose `ToolEvent::OutputChunk` lacks an id. - `Channel::send_diff` gains a `tool_call_id: &str` parameter. (#3711) - -- fix(cli): `zeph cocoon doctor` now reports `[FAIL]` for `cocoon_client_url` with an invalid scheme - (e.g. `ftp://`). `check_config_present` previously returned `[OK]` without calling - `entry.validate()`, silently accepting any URL scheme. The fix adds a `validate()` guard that - pushes a `CheckResult::fail` with the scheme error and returns early. (#3694) - -### Added - - feat(hooks): `PreToolUse` and `PostToolUse` hook events for the main agent and subagent paths. New `[[hooks.pre_tool_use]]` and `[[hooks.post_tool_use]]` config sections accept `HookMatcher` entries (pipe-separated tool name patterns). Hooks fire with env vars: @@ -108,18 +73,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). and `ZEPH_TOOL_DURATION_MS` (post hooks only). PreToolUse fires before the `RuntimeLayer` permission check (observers see all attempted calls). Hook dispatch is fail-open at the agent level; `fail_closed` in a `HookDef` aborts the hook-chain sequence only. Closes #3698. - - feat(tui): native terminal text selection without Shift modifier. `EnableMouseCapture` replaced with alternate-scroll mode (`\x1b[?1007h`/`\x1b[?1007l`) so the terminal translates scroll-wheel events into arrow keys. Chat scrolling is preserved; `AppEvent::MouseScroll` removed from the event model. Panic hook updated to emit `DisableAlternateScroll` on crash. Closes #3685. (#3685) - - feat(tui): clipboard shortcuts for copying assistant replies. New `clipboard` module with `ClipboardHandle` backed by arboard (local) with OSC 52 fallback (SSH/tmux). SSH detected via `SSH_TTY`, `SSH_CONNECTION`, `SSH_CLIENT`. `Ctrl+O` and `/copy` slash command copy the last assistant message to clipboard. `clipboard` feature flag (default-on) gates the arboard dependency for headless builds. Closes #3685. (#3685) - - feat(tui): Two-tier tool rendering and `ToolDensity` config — replaces the boolean `compact_tools` toggle with a three-state `ToolDensity` enum (`compact` / `inline` / `block`) that cycles with the `c` key. `inline` (default) renders a head (2 lines) + ellipsis @@ -128,12 +90,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). (green `●` / red `●`); streaming messages show the braille spinner. `ToolKind` classifies tools into Run / Explore / Edit / Web / Mcp / Other; consecutive Run and Explore calls are eligible for future grouping. `tool_density` is configurable in the `[tui]` config section. (#3686) - - feat(llm): Cocoon live integration tests — 6 `#[ignore]`-gated tests covering `health_check`, `list_models`, `chat_round_trip`, `chat_stream`, `chat_with_tools`, and `doctor` checks. Tests require `COCOON_TEST_URL` env var and skip gracefully without it; `#[ignore]` attributes include reason strings. Requires `cocoon` feature. (#3675) - - feat(tui): Cocoon TUI integration — `/cocoon status` and `/cocoon models` palette commands dispatch through the `CommandRegistry` (same as `/acp`) and display sidecar health and available models. Status bar shows `Cocoon: healthy (N models, M workers, X TON)` or @@ -142,13 +102,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). HTTP calls after executor starvation. All I/O paths instrumented with `tui.cocoon.poll`, `tui.cocoon.status`, and `tui.cocoon.models` tracing spans. Requires `cocoon` + `tui` features. (#3673) - - feat(cli): `zeph cocoon doctor [--json] [--timeout-secs N]` diagnostic subcommand for Cocoon sidecar connectivity checks. Runs 6 ordered checks: config entry presence, sidecar HTTP reachability (`GET /stats`), proxy connection, worker count, model listing, and vault key resolution. Downstream checks gracefully skip (WARN) when the sidecar is unreachable. `--json` emits a structured JSON envelope with `schema_version: 1`. Requires `cocoon` feature. (#3672) +### Fixed + +- fix(security): wire `ShadowProbeExecutor` into the agent executor chain (`src/runner.rs`). + `ShadowSentinel` is now instantiated when `security.shadow_sentinel.enabled = true` and + inserted between `ScopedToolExecutor` and `PolicyGateExecutor` as required by spec 050 §Phase 2. + Adds `ShadowSentinelProbeGateAdapter` bridge to avoid circular crate dependency. Wires + `sentinel.advance_turn()` into `begin_turn()`. Closes #3739. +- fix(hooks): `pre_tool_use` hooks now fire for tool calls intercepted by the utility gate; + previously the hook block was skipped because `check_call_gates` returned early with `continue`. + Closes #3738. +- fix(tui): parallel tool call output no longer gets cross-contaminated in the TUI. `tool_call_id` + is now threaded from `ToolCall` through `ShellExecutor` → `ToolEvent::OutputChunk` → + `tui_bridge` → `AgentEvent::ToolOutputChunk/ToolStart/ToolOutput`. The TUI uses id-based + lookup when `tool_call_id` is non-empty; on miss it drops the chunk with a `warn!` log + instead of falling back to the last streaming message (which was the source of the bug). + The legacy empty-id path retains the old `rposition` fallback for backwards compatibility. + Closes #3688. (#3708) +- fix(tui): `handle_diff_ready` now correlates diffs to tool messages by `tool_call_id` instead of + a position-based `.rev().find()` scan, preventing diffs from attaching to the wrong message when + multiple tool calls are in flight. `AgentEvent::DiffReady` is now a struct variant carrying + `tool_call_id: String`. `ToolOutputChunk` lookup similarly uses id-based matching with a fallback + to the last streaming Tool message for shell tools whose `ToolEvent::OutputChunk` lacks an id. + `Channel::send_diff` gains a `tool_call_id: &str` parameter. (#3711) +- fix(cli): `zeph cocoon doctor` now reports `[FAIL]` for `cocoon_client_url` with an invalid scheme + (e.g. `ftp://`). `check_config_present` previously returned `[OK]` without calling + `entry.validate()`, silently accepting any URL scheme. The fix adds a `validate()` guard that + pushes a `CheckResult::fail` with the scheme error and returns early. (#3694) +- fix(security): extend `classify_tool` to recognise bare shell and file-write tool IDs + (`bash`, `shell`, `write_file`, `write`, `create_file`) so `ShadowProbeExecutor` probes + trigger correctly when callers omit the `qualified::` prefix. Closes #3744. + ### Changed - refactor(common,context): resolve `zeph-context → zeph-memory` same-layer violation (#3665). @@ -157,15 +147,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `GraphRecallParams`, `TokenCounting`, `ContextMemoryBackend`) to `zeph-common::memory`. Added `SemanticMemoryBackend` adapter and `build_memory_router()` in `zeph-agent-context`. `zeph-context` no longer imports `zeph-memory`. Exception note removed from `specs/constitution.md`. - - build: add `profiling` and `sandbox` to default Cargo features — tracing spans are compiled by default for diagnostics; macOS Seatbelt / Linux Landlock sandbox is available without `--features sandbox` (still runtime-disabled unless `tools.sandbox.enabled = true`) - build: consolidate `self-check`, `env-vault`, and `task-metrics` as always-on — these were pure behavioral markers with no optional deps, violating the feature flag decision rule (spec 029 §2) - -### Fixed - - docs(specs): update spec 001 §9 and spec 029 §3.1/§4/§5.3 to reflect actual default feature set (was documenting `default = ["scheduler", "sqlite"]` since v0.18 while reality had 5 features since v0.20) @@ -5793,7 +5779,8 @@ let agent = Agent::new(provider, channel, &skills_prompt, executor); - Agent::run() uses tokio::select! to race channel messages against shutdown signal [0.16.0]: https://github.com/bug-ops/zeph/compare/v0.15.3...v0.16.0 -[Unreleased]: https://github.com/bug-ops/zeph/compare/v0.20.2...HEAD +[Unreleased]: https://github.com/bug-ops/zeph/compare/v0.21.0...HEAD +[0.21.0]: https://github.com/bug-ops/zeph/compare/v0.20.2...v0.21.0 [0.20.2]: https://github.com/bug-ops/zeph/compare/v0.20.1...v0.20.2 [0.20.1]: https://github.com/bug-ops/zeph/compare/v0.20.0...v0.20.1 [0.20.0]: https://github.com/bug-ops/zeph/compare/v0.19.3...v0.20.0 diff --git a/Cargo.lock b/Cargo.lock index 5029c4a55..fac69bc23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10290,7 +10290,7 @@ dependencies = [ [[package]] name = "zeph" -version = "0.20.2" +version = "0.21.0" dependencies = [ "anyhow", "async-trait", @@ -10359,7 +10359,7 @@ dependencies = [ [[package]] name = "zeph-a2a" -version = "0.20.2" +version = "0.21.0" dependencies = [ "axum 0.8.9", "base64 0.22.1", @@ -10389,7 +10389,7 @@ dependencies = [ [[package]] name = "zeph-acp" -version = "0.20.2" +version = "0.21.0" dependencies = [ "agent-client-protocol", "agent-client-protocol-tokio", @@ -10431,7 +10431,7 @@ dependencies = [ [[package]] name = "zeph-agent-context" -version = "0.20.2" +version = "0.21.0" dependencies = [ "chrono", "futures", @@ -10453,7 +10453,7 @@ dependencies = [ [[package]] name = "zeph-agent-feedback" -version = "0.20.2" +version = "0.21.0" dependencies = [ "regex", "schemars 1.2.1", @@ -10468,7 +10468,7 @@ dependencies = [ [[package]] name = "zeph-agent-persistence" -version = "0.20.2" +version = "0.21.0" dependencies = [ "serde", "serde_json", @@ -10484,7 +10484,7 @@ dependencies = [ [[package]] name = "zeph-agent-tools" -version = "0.20.2" +version = "0.21.0" dependencies = [ "futures", "serde", @@ -10506,7 +10506,7 @@ dependencies = [ [[package]] name = "zeph-bench" -version = "0.20.2" +version = "0.21.0" dependencies = [ "clap", "schemars 1.2.1", @@ -10527,7 +10527,7 @@ dependencies = [ [[package]] name = "zeph-channels" -version = "0.20.2" +version = "0.21.0" dependencies = [ "axum 0.8.9", "criterion", @@ -10555,7 +10555,7 @@ dependencies = [ [[package]] name = "zeph-commands" -version = "0.20.2" +version = "0.21.0" dependencies = [ "serde", "thiserror 2.0.18", @@ -10565,7 +10565,7 @@ dependencies = [ [[package]] name = "zeph-common" -version = "0.20.2" +version = "0.21.0" dependencies = [ "blake3", "cpu-time", @@ -10592,7 +10592,7 @@ dependencies = [ [[package]] name = "zeph-config" -version = "0.20.2" +version = "0.21.0" dependencies = [ "dirs", "insta", @@ -10612,7 +10612,7 @@ dependencies = [ [[package]] name = "zeph-context" -version = "0.20.2" +version = "0.21.0" dependencies = [ "blake3", "futures", @@ -10632,7 +10632,7 @@ dependencies = [ [[package]] name = "zeph-core" -version = "0.20.2" +version = "0.21.0" dependencies = [ "age", "base64 0.22.1", @@ -10699,7 +10699,7 @@ dependencies = [ [[package]] name = "zeph-db" -version = "0.20.2" +version = "0.21.0" dependencies = [ "regex", "sqlx", @@ -10714,7 +10714,7 @@ dependencies = [ [[package]] name = "zeph-experiments" -version = "0.20.2" +version = "0.21.0" dependencies = [ "futures", "ordered-float 5.3.0", @@ -10737,7 +10737,7 @@ dependencies = [ [[package]] name = "zeph-gateway" -version = "0.20.2" +version = "0.21.0" dependencies = [ "axum 0.8.9", "blake3", @@ -10756,7 +10756,7 @@ dependencies = [ [[package]] name = "zeph-index" -version = "0.20.2" +version = "0.21.0" dependencies = [ "futures", "ignore", @@ -10790,7 +10790,7 @@ dependencies = [ [[package]] name = "zeph-llm" -version = "0.20.2" +version = "0.21.0" dependencies = [ "async-stream", "audioadapter-buffers", @@ -10838,7 +10838,7 @@ dependencies = [ [[package]] name = "zeph-mcp" -version = "0.20.2" +version = "0.21.0" dependencies = [ "async-trait", "blake3", @@ -10871,7 +10871,7 @@ dependencies = [ [[package]] name = "zeph-memory" -version = "0.20.2" +version = "0.21.0" dependencies = [ "arc-swap", "blake3", @@ -10910,7 +10910,7 @@ dependencies = [ [[package]] name = "zeph-orchestration" -version = "0.20.2" +version = "0.21.0" dependencies = [ "blake3", "dirs", @@ -10937,7 +10937,7 @@ dependencies = [ [[package]] name = "zeph-plugins" -version = "0.20.2" +version = "0.21.0" dependencies = [ "anyhow", "dirs", @@ -10959,7 +10959,7 @@ dependencies = [ [[package]] name = "zeph-sanitizer" -version = "0.20.2" +version = "0.21.0" dependencies = [ "proptest", "regex", @@ -10979,7 +10979,7 @@ dependencies = [ [[package]] name = "zeph-scheduler" -version = "0.20.2" +version = "0.21.0" dependencies = [ "chrono", "cron", @@ -10999,7 +10999,7 @@ dependencies = [ [[package]] name = "zeph-skills" -version = "0.20.2" +version = "0.21.0" dependencies = [ "anyhow", "blake3", @@ -11033,7 +11033,7 @@ dependencies = [ [[package]] name = "zeph-subagent" -version = "0.20.2" +version = "0.21.0" dependencies = [ "dirs", "indoc", @@ -11060,7 +11060,7 @@ dependencies = [ [[package]] name = "zeph-tools" -version = "0.20.2" +version = "0.21.0" dependencies = [ "arc-swap", "dashmap", @@ -11107,7 +11107,7 @@ dependencies = [ [[package]] name = "zeph-tui" -version = "0.20.2" +version = "0.21.0" dependencies = [ "arboard", "base64 0.22.1", @@ -11147,7 +11147,7 @@ dependencies = [ [[package]] name = "zeph-vault" -version = "0.20.2" +version = "0.21.0" dependencies = [ "age", "proptest", diff --git a/Cargo.toml b/Cargo.toml index 5a34428b9..a8ebf6a42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ resolver = "3" [workspace.package] edition = "2024" rust-version = "1.95" -version = "0.20.2" +version = "0.21.0" authors = ["bug-ops"] license = "MIT" repository = "https://github.com/bug-ops/zeph" @@ -144,35 +144,35 @@ uuid = "1.23.1" walkdir = "2.5" wiremock = "0.6.5" zeroize = { version = "1.8.2", default-features = false } -zeph-a2a = { path = "crates/zeph-a2a", version = "0.20.2" } -zeph-agent-context = { path = "crates/zeph-agent-context", version = "0.20.2" } -zeph-agent-feedback = { path = "crates/zeph-agent-feedback", version = "0.20.2" } -zeph-agent-persistence = { path = "crates/zeph-agent-persistence", version = "0.20.2" } -zeph-agent-tools = { path = "crates/zeph-agent-tools", version = "0.20.2" } -zeph-bench = { path = "crates/zeph-bench", version = "0.20.2" } -zeph-acp = { path = "crates/zeph-acp", version = "0.20.2" } -zeph-db = { path = "crates/zeph-db", default-features = false, version = "0.20.2" } -zeph-channels = { path = "crates/zeph-channels", version = "0.20.2" } -zeph-common = { path = "crates/zeph-common", version = "0.20.2" } -zeph-config = { path = "crates/zeph-config", version = "0.20.2" } -zeph-commands = { path = "crates/zeph-commands", version = "0.20.2" } -zeph-context = { path = "crates/zeph-context", version = "0.20.2" } -zeph-core = { path = "crates/zeph-core", version = "0.20.2" } -zeph-experiments = { path = "crates/zeph-experiments", version = "0.20.2" } -zeph-gateway = { path = "crates/zeph-gateway", version = "0.20.2" } -zeph-index = { path = "crates/zeph-index", version = "0.20.2" } -zeph-llm = { path = "crates/zeph-llm", version = "0.20.2" } -zeph-mcp = { path = "crates/zeph-mcp", version = "0.20.2" } -zeph-memory = { path = "crates/zeph-memory", default-features = false, version = "0.20.2" } -zeph-scheduler = { path = "crates/zeph-scheduler", version = "0.20.2" } -zeph-skills = { path = "crates/zeph-skills", version = "0.20.2" } -zeph-tools = { path = "crates/zeph-tools", version = "0.20.2" } -zeph-tui = { path = "crates/zeph-tui", version = "0.20.2" } -zeph-vault = { path = "crates/zeph-vault", version = "0.20.2" } -zeph-orchestration = { path = "crates/zeph-orchestration", version = "0.20.2" } -zeph-plugins = { path = "crates/zeph-plugins", version = "0.20.2" } -zeph-sanitizer = { path = "crates/zeph-sanitizer", version = "0.20.2" } -zeph-subagent = { path = "crates/zeph-subagent", version = "0.20.2" } +zeph-a2a = { path = "crates/zeph-a2a", version = "0.21.0" } +zeph-agent-context = { path = "crates/zeph-agent-context", version = "0.21.0" } +zeph-agent-feedback = { path = "crates/zeph-agent-feedback", version = "0.21.0" } +zeph-agent-persistence = { path = "crates/zeph-agent-persistence", version = "0.21.0" } +zeph-agent-tools = { path = "crates/zeph-agent-tools", version = "0.21.0" } +zeph-bench = { path = "crates/zeph-bench", version = "0.21.0" } +zeph-acp = { path = "crates/zeph-acp", version = "0.21.0" } +zeph-db = { path = "crates/zeph-db", default-features = false, version = "0.21.0" } +zeph-channels = { path = "crates/zeph-channels", version = "0.21.0" } +zeph-common = { path = "crates/zeph-common", version = "0.21.0" } +zeph-config = { path = "crates/zeph-config", version = "0.21.0" } +zeph-commands = { path = "crates/zeph-commands", version = "0.21.0" } +zeph-context = { path = "crates/zeph-context", version = "0.21.0" } +zeph-core = { path = "crates/zeph-core", version = "0.21.0" } +zeph-experiments = { path = "crates/zeph-experiments", version = "0.21.0" } +zeph-gateway = { path = "crates/zeph-gateway", version = "0.21.0" } +zeph-index = { path = "crates/zeph-index", version = "0.21.0" } +zeph-llm = { path = "crates/zeph-llm", version = "0.21.0" } +zeph-mcp = { path = "crates/zeph-mcp", version = "0.21.0" } +zeph-memory = { path = "crates/zeph-memory", default-features = false, version = "0.21.0" } +zeph-scheduler = { path = "crates/zeph-scheduler", version = "0.21.0" } +zeph-skills = { path = "crates/zeph-skills", version = "0.21.0" } +zeph-tools = { path = "crates/zeph-tools", version = "0.21.0" } +zeph-tui = { path = "crates/zeph-tui", version = "0.21.0" } +zeph-vault = { path = "crates/zeph-vault", version = "0.21.0" } +zeph-orchestration = { path = "crates/zeph-orchestration", version = "0.21.0" } +zeph-plugins = { path = "crates/zeph-plugins", version = "0.21.0" } +zeph-sanitizer = { path = "crates/zeph-sanitizer", version = "0.21.0" } +zeph-subagent = { path = "crates/zeph-subagent", version = "0.21.0" } [workspace.lints.rust] unsafe_code = "deny" diff --git a/README.md b/README.md index 3259b11e5..820ae7abe 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ [![CI](https://img.shields.io/github/actions/workflow/status/bug-ops/zeph/ci.yml?branch=main&label=CI)](https://github.com/bug-ops/zeph/actions) [![codecov](https://codecov.io/gh/bug-ops/zeph/graph/badge.svg?token=S5O0GR9U6G)](https://codecov.io/gh/bug-ops/zeph) [![MSRV](https://img.shields.io/badge/MSRV-1.95-blue)](https://www.rust-lang.org) + [![Tests](https://img.shields.io/badge/tests-9139-brightgreen)](https://github.com/bug-ops/zeph/actions) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) @@ -201,12 +202,12 @@ cargo build --release --features full | Area | Highlights | |---|---| -| Memory | SQLite/PostgreSQL history, embedded SQLite vectors or Qdrant, graph memory, SYNAPSE, SleepGate, APEX-MEM write-quality gates, MemCoT Zoom-In/Out recall views, document RAG. | +| Memory | SQLite/PostgreSQL history, embedded SQLite vectors or Qdrant, [graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html), SYNAPSE, SleepGate, APEX-MEM write-quality gates, BeliefMem probabilistic edge layer, MemCoT Zoom-In/Out recall views, document RAG. | | Context | Goal-aware compaction, TypedPage assembler pipeline, TACO output compression, tool-output archive, session recap, active-goal injection. | -| Skills | `SKILL.md` registry, hot reload, BM25 + embedding matching, trust levels, self-learning skill improvement. | -| Providers | Ollama, Claude, OpenAI, Gemini, OpenAI-compatible APIs, Gonka native inference, Candle local inference, adaptive routing. | -| Tools | Shell, file, web, MCP, tool quotas, approval gates, audit trail, sandboxing, output compression, speculative dispatch, TrajectorySentinel capability governance. | -| Interfaces | CLI, TUI, Telegram, Discord, Slack, ACP, A2A, HTTP gateway, scheduler daemon. | +| Skills | `SKILL.md` registry, hot reload, BM25 + embedding matching, trust levels, [self-learning skill improvement](https://bug-ops.github.io/zeph/guides/self-learning.html). | +| Providers | Ollama, Claude, OpenAI, Gemini, OpenAI-compatible APIs, [Gonka](https://bug-ops.github.io/zeph/guides/gonka.html) native inference, [Cocoon](https://bug-ops.github.io/zeph/guides/cocoon.html) decentralized TEE inference, Candle local inference, adaptive routing. | +| Tools | Shell, file, web, MCP, tool quotas, approval gates, audit trail, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), output compression, speculative dispatch, [ShadowSentinel](https://bug-ops.github.io/zeph/reference/security/shadow-sentinel.html) safety probes, TrajectorySentinel capability governance. | +| Interfaces | CLI, TUI, [Telegram](https://bug-ops.github.io/zeph/guides/telegram.html) (with Guest Mode and Bot-to-Bot), Discord, Slack, ACP, A2A, HTTP gateway, scheduler daemon. | | Code intelligence | Tree-sitter indexing, semantic repo map, LSP diagnostics and hover context through MCP. | | Observability | Debug dumps, JSONL mode, Prometheus metrics, OpenTelemetry traces, profiling builds. | diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index d7cef9f90..96db80d35 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -32,6 +32,7 @@ - [Use a Cloud Provider](guides/cloud-provider.md) - [Gonka Provider](guides/gonka.md) +- [Cocoon Decentralized TEE](guides/cocoon.md) - [Configuration Recipes](guides/config-recipes.md) - [Run via Telegram](guides/telegram.md) - [Add Custom Skills](guides/custom-skills.md) @@ -96,6 +97,7 @@ - [MCP Security](reference/security/mcp.md) - [Untrusted Content Isolation](reference/security/untrusted-content-isolation.md) - [File Read Sandbox](reference/security/file-sandbox.md) + - [ShadowSentinel Safety Probing](reference/security/shadow-sentinel.md) # Development diff --git a/book/src/advanced/tui.md b/book/src/advanced/tui.md index 4ad4e4ac5..653e29af0 100644 --- a/book/src/advanced/tui.md +++ b/book/src/advanced/tui.md @@ -218,7 +218,109 @@ When the agent uses write or edit tools, the TUI renders file changes as syntax- Syntax highlighting (via tree-sitter) is preserved within diff lines for supported languages (Rust, Python, JavaScript, JSON, TOML, Bash). -### Compact and Expanded Modes +## Tool Output Density + +Tool execution output (shell commands, file operations, web searches) can be displayed in three different densities to match your preferences. Control density with the `c` key, and configure default density in your config. + +### Compact Density + +Shows a single-line summary per tool: + +```text +● Ran 3 commands +● Explored 2 files +● Updated 5 lines +``` + +Consecutive tool calls of the same type are grouped together. Click to expand individual tool. + +### Inline Density (Default) + +Balances readability with screen space. Shows: +- Tool name and primary arguments (first 2 lines) +- Abbreviated middle section (ellipsis if >6 lines) +- Last 2 lines of output + +```text +● shell: git status + On branch main + ... + modified: src/main.rs +``` + +Consecutive tools of the same category are grouped with a count badge: + +```text +● Ran 3 commands + ├─ git status + ├─ cargo build --release + └─ cargo test +``` + +### Block Density + +Shows full tool output without truncation: + +```text +● shell: cargo test + running 12 tests + test result: ok. 12 passed; 0 failed + ... + test_compression ... ok +``` + +### Configuration + +Set default density in your config: + +```toml +[tui] +tool_density = "inline" # compact, inline, or block (default: inline) +``` + +Press `c` during a conversation to cycle through densities without config changes. + +### Tool Grouping + +Consecutive tool calls with the same category are automatically grouped when `tool_density = "inline"` or `"compact"`. Categories are: + +| Category | Tools | +|----------|-------| +| Run | shell, bash, sh | +| Explore | ls, find, file_read, etc. | +| Edit | write_file, edit_file, rename, delete | +| Web | web_scrape, brave_search, etc. | +| MCP | All MCP tools | +| Other | Unrecognized tools | + +Groups break on role change (user message or system message), tool kind change, or when a tool is streaming. + +## Text Selection and Clipboard + +### Native Text Selection + +The TUI supports native terminal text selection without the Shift modifier. Select text by: + +1. Click and drag to select +2. Use keyboard selection (Shift+Arrow) in compatible terminals +3. Triple-click to select a full line or paragraph + +Selected text is automatically copied to the system clipboard when you release the mouse or press `Enter`. + +### Clipboard Shortcuts + +Copy the last assistant message to your system clipboard: + +- **`Ctrl+O`** — Copy last assistant response +- **`/copy`** — Copy command (alternative method) + +SSH and tmux users: clipboard data is sent via OSC 52 escape sequences, allowing Zeph to write to your local clipboard even on remote machines. + +### SSH and Tmux Detection + +When running over SSH (detected via `SSH_TTY`, `SSH_CONNECTION`, `SSH_CLIENT` environment variables), clipboard operations automatically fall back to the OSC 52 protocol. This allows clipboard functionality to work in tmux sessions and SSH connections without needing a local xclip or pbcopy. + +### Compact and Expanded Modes for Diffs Diffs default to **compact mode**, showing a single-line summary (file path with added/removed line counts). Press `e` to toggle **expanded mode**, which renders the full line-by-line diff with syntax highlighting and colored backgrounds. diff --git a/book/src/concepts/graph-memory.md b/book/src/concepts/graph-memory.md index 53b27acc8..da7b6f228 100644 --- a/book/src/concepts/graph-memory.md +++ b/book/src/concepts/graph-memory.md @@ -333,6 +333,63 @@ Entity names, relations, and targets are escaped — newlines and angle brackets Graph facts receive 3% of the available context budget (carved from the semantic recall allocation, which drops from 8% to 5%). When the budget is zero (unlimited mode) or graph memory is disabled, no budget is allocated and no facts are injected. +## BeliefMem: Probabilistic Edge Layer + +BeliefMem (Belief Memory) extends graph memory with a probabilistic layer for uncertain facts. Instead of immediately committing facts as edges, BeliefMem accumulates evidence and tracks confidence scores before promotion to the committed graph. + +**Use cases:** +- Track emerging patterns that haven't yet been confirmed +- Handle contradictory or uncertain information gracefully +- Preserve uncertainty in retrieval — avoid treating unconfirmed facts as ground truth + +### How It Works + +BeliefMem maintains two parallel layers: + +1. **Pending beliefs** — candidate facts with probability weights from initial extraction +2. **Belief evidence** — evidence accumulation via Noisy-OR with optional temporal decay + +When evidence for a fact accumulates and crosses a promotion threshold (default: 0.85 confidence), the pending belief is promoted to a committed edge in the main graph. + +**Example workflow:** +- Extraction observes: "User might prefer Rust" (confidence: 0.6) +- Extraction later observes: "User uses Rust for most projects" (confidence: 0.7) +- Evidence combines via Noisy-OR: ~0.88 confidence +- Belief is promoted and becomes a committed graph edge + +### Configuration + +Enable BeliefMem under `[memory.graph.belief_mem]`: + +```toml +[memory.graph.belief_mem] +enabled = true # Enable probabilistic belief layer (default: false) +promote_threshold = 0.85 # Min confidence for promotion to committed edge (default: 0.85) +belief_decay_rate = 0.0 # Temporal decay on pending beliefs; 0.0 = disabled (default) + # Range: [0.0, 10.0]. Formula: 1/(1 + age_days * rate) +max_pending_beliefs = 1000 # Cap on pending beliefs to prevent unbounded growth +``` + +| Field | Default | Description | +|-------|---------|-------------| +| `enabled` | false | Enable BeliefMem (default: false) | +| `promote_threshold` | 0.85 | Confidence threshold for edge promotion (range: 0.5–1.0) | +| `belief_decay_rate` | 0.0 | Temporal decay factor for aging beliefs; 0.0 = disabled | +| `max_pending_beliefs` | 1000 | Maximum pending beliefs before LRU eviction | + +### Uncertainty-Preserving Retrieval + +When BeliefMem is enabled and graph recall finds no committed edge between two entities, Zeph automatically queries pending beliefs and returns top-K candidates ranked by confidence. This provides graceful fallback behavior when facts are still being accumulated. + +### Storage + +BeliefMem uses two new SQLite tables (created by migration 084): + +- `pending_beliefs` — candidate facts with probability scores +- `belief_evidence` — evidence records supporting promotion + +These tables are independent of the main graph layer and are automatically cleaned up during graph eviction. + ## Configuration Enable graph memory in your `config.toml`: @@ -341,6 +398,7 @@ Enable graph memory in your `config.toml`: [memory.graph] enabled = true # Enable graph memory (default: false) extract_model = "" # LLM model for extraction; empty = agent's model +extract_provider = "" # Provider name for extraction (bypasses quality gate) max_entities_per_message = 10 max_edges_per_message = 15 max_hops = 2 # BFS traversal depth (default: 2) @@ -358,6 +416,12 @@ temporal_decay_rate = 0.0 # Recency boost for graph recall; 0.0 = disabl # Range: [0.0, 10.0]. Formula: 1/(1 + age_days * rate) edge_history_limit = 100 # Max versions returned by edge_history() per source+predicate pair +[memory.graph.belief_mem] +enabled = false # Enable probabilistic belief layer (default: false) +promote_threshold = 0.85 # Confidence threshold for edge promotion (default: 0.85) +belief_decay_rate = 0.0 # Temporal decay on pending beliefs (default: 0.0) +max_pending_beliefs = 1000 # Max pending beliefs before eviction (default: 1000) + [memory.graph.note_linking] # enabled = false # Enable A-MEM note linking after extraction (default: false) # similarity_threshold = 0.85 # Min cosine similarity to create a similar_to edge (default: 0.85) diff --git a/book/src/concepts/hooks.md b/book/src/concepts/hooks.md index 3ce1b054d..5fa18ee21 100644 --- a/book/src/concepts/hooks.md +++ b/book/src/concepts/hooks.md @@ -1,9 +1,45 @@ # Reactive Hooks -Zeph can run shell commands automatically in response to environment changes. Two hook events are supported: working directory changes and file system changes. +Zeph can run shell commands automatically in response to environment changes and tool execution events. Four hook events are supported: working directory changes, file system changes, tool execution before/after. ## Hook Types +### `pre_tool_use` and `post_tool_use` + +Fires before and after a tool is executed. Useful for logging, monitoring, security auditing, or modifying the environment before/after tool runs. + +**Pre-execution (before tool runs):** + +```toml +[[hooks.pre_tool_use]] +tools = "shell|bash|sh" # Pipe-separated tool name patterns (glob matching) +command = "echo" +args = ["About to run: $ZEPH_TOOL_NAME with args: $ZEPH_TOOL_ARGS_JSON"] +``` + +**Post-execution (after tool runs):** + +```toml +[[hooks.post_tool_use]] +tools = "write_file|edit_file" # File write tools +command = "git" +args = ["add", "$ZEPH_TOOL_NAME"] +fail_closed = false # If true, hook failure aborts the tool chain (default: false) +``` + +Environment variables available to hook processes: + +| Variable | Available in | Description | +|----------|---|-------------| +| `ZEPH_TOOL_NAME` | pre + post | Tool name (e.g., `shell`, `web_scrape`) | +| `ZEPH_TOOL_ARGS_JSON` | pre + post | Tool arguments as JSON (truncated to 64 KiB via UTF-8 boundary) | +| `ZEPH_TOOL_DURATION_MS` | post only | Time taken to execute the tool (milliseconds) | +| `ZEPH_SESSION_ID` | pre + post (main agent only) | Session ID; omitted in subagent hooks | + +**Hook firing order:** + +Pre-hooks fire **before** utility gate and permission checks. This means observers can see all tool invocations, including those that would be blocked by policies. Post-hooks fire after successful execution. + ### `cwd_changed` Fires when the agent's working directory changes — either via the `set_working_directory` tool or an explicit directory change detected after tool execution. @@ -70,6 +106,20 @@ The indicator disappears once all hook commands for that event have completed. ## Configuration Reference ```toml +# Pre-tool-use hooks — run before any tool execution +[[hooks.pre_tool_use]] +tools = "shell|bash|sh" # Tool name pattern (pipe-separated, glob matching) +command = "echo" +args = ["Running: $ZEPH_TOOL_NAME"] +fail_closed = false # If true, hook failure aborts the tool (default: false) + +# Post-tool-use hooks — run after tool execution completes +[[hooks.post_tool_use]] +tools = "write_file" +command = "git" +args = ["add", "$ZEPH_TOOL_NAME"] +fail_closed = false # If true, hook failure blocks subsequent tools + # cwd_changed hooks — run in order when the working directory changes [[hooks.cwd_changed]] command = "echo" @@ -87,6 +137,14 @@ args = ["check", "--quiet"] | Field | Type | Default | Description | |-------|------|---------|-------------| +| `hooks.pre_tool_use[].tools` | `string` | — | Pipe-separated tool name patterns to match | +| `hooks.pre_tool_use[].command` | `string` | — | Executable to run | +| `hooks.pre_tool_use[].args` | `Vec` | `[]` | Arguments (env vars expanded) | +| `hooks.pre_tool_use[].fail_closed` | `bool` | false | If true, hook failure aborts the tool chain | +| `hooks.post_tool_use[].tools` | `string` | — | Pipe-separated tool name patterns to match | +| `hooks.post_tool_use[].command` | `string` | — | Executable to run | +| `hooks.post_tool_use[].args` | `Vec` | `[]` | Arguments (env vars expanded) | +| `hooks.post_tool_use[].fail_closed` | `bool` | false | If true, hook failure aborts the tool chain | | `hooks.cwd_changed[].command` | `string` | — | Executable to run | | `hooks.cwd_changed[].args` | `Vec` | `[]` | Arguments (env vars expanded) | | `hooks.file_changed.watch_paths` | `Vec` | `[]` | Paths to monitor | @@ -94,6 +152,26 @@ args = ["check", "--quiet"] | `hooks.file_changed.handlers[].command` | `string` | — | Executable to run | | `hooks.file_changed.handlers[].args` | `Vec` | `[]` | Arguments (env vars expanded) | +### Tool Pattern Matching + +Tool name patterns support pipe-separated patterns and glob matching: + +```toml +# Match exact tool names +tools = "shell" # Only the shell tool + +# Match multiple tools +tools = "shell|bash|sh" # Any shell variant + +# Glob patterns (glob syntax) +tools = "write_*" # write_file, write_dir, etc. + +# Combine exact and globs +tools = "shell|*_file" # shell tool or any *_file tool +``` + +Patterns are matched case-sensitively. An empty pattern matches no tools. + ## Hook Tracing and Instrumentation All hook execution is instrumented with distributed tracing. Each hook invocation generates: diff --git a/book/src/guides/cocoon.md b/book/src/guides/cocoon.md new file mode 100644 index 000000000..d98056814 --- /dev/null +++ b/book/src/guides/cocoon.md @@ -0,0 +1,231 @@ +# Cocoon Decentralized TEE Provider + +[Cocoon](https://cocoon.ai) is a decentralized inference network that executes LLM requests in Trusted Execution Environments (TEEs) on a peer-to-peer network of secure nodes. Zeph supports native integration with optional speech-to-text transcription via the Cocoon sidecar. + +Cocoon is particularly useful for: + +- **Confidential inference** — Requests execute in hardware-isolated TEEs; no server-side model access +- **Privacy compliance** — End-to-end encrypted communication path with zero-knowledge server operations +- **Flexible deployment** — Run locally with a sidecar or connect to public Cocoon nodes +- **Multi-modal support** — Text chat, tool use, and STT transcription in one provider + +## Setup + +### Prerequisites + +1. Install the Cocoon sidecar (local deployment only): + ```bash + # Download from https://cocoon.ai or build from source + cocoon --version + ``` + +2. Start the sidecar on the default port (8765): + ```bash + cocoon serve + # Or on a custom port: + cocoon serve --port 9000 + ``` + +### Configuration + +Add a Cocoon provider entry to your config: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon-local" +base_url = "http://localhost:8765" # Sidecar endpoint +model = "llama2-7b" # Available model on sidecar +``` + +Or store the base URL in the vault for security: + +```bash +zeph vault set ZEPH_COCOON_CLIENT_URL "http://localhost:8765" +``` + +Then reference it in config: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon-local" +base_url = "${ZEPH_COCOON_CLIENT_URL}" +model = "llama2-7b" +``` + +## Features + +### Chat and Streaming + +Cocoon supports both single-turn and streaming chat: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon" +base_url = "http://localhost:8765" +model = "llama2-7b" +max_tokens = 2048 +temperature = 0.7 +``` + +### Tool Use (Function Calling) + +Cocoon fully supports tool definitions and structured function calling: + +- Define tools in your skills and system prompt +- Zeph automatically formats tool calls for Cocoon +- Streaming tool use is supported with incremental JSON parsing + +### Speech-to-Text (STT) + +The Cocoon sidecar includes a Whisper-compatible STT endpoint at `/v1/audio/transcriptions`. Configure Zeph to use it: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon-stt" +stt_model = "whisper-1" # Enable STT on this provider +``` + +When configured, Zeph automatically transcribes voice messages and Telegram audio notes using this provider. See [Audio & Vision](../advanced/multimodal.md) for more details. + +### Per-Token Pricing (Cocoon Models) + +Unlike cloud providers, Cocoon models may not be in Zeph's built-in pricing table. Configure per-1K-token pricing for accurate cost tracking: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon-custom" +base_url = "http://localhost:8765" +model = "my-custom-model" + +# Per-1K-token pricing in cents (prompt + completion) +cocoon_pricing = { prompt_cents = 1, completion_cents = 2 } +``` + +This enables the cost tracker to report accurate token consumption and pricing for your Cocoon inference. + +### Multi-Model Routing + +Combine Cocoon with other providers for cost-effective multi-tier inference: + +```toml +[[llm.providers]] +type = "cocoon" +name = "cocoon-smart" +base_url = "http://localhost:8765" +model = "llama2-13b" + +[[llm.providers]] +type = "ollama" +name = "ollama-fast" +base_url = "http://localhost:11434" +model = "qwen3:1.7b" + +[llm] +routing = "triage" # Route by complexity + +[llm.complexity_routing] +triage_provider = "ollama-fast" +simple = "ollama-fast" # Quick questions → fast model +medium = "ollama-fast" # Moderate tasks → fast model +complex = "cocoon-smart" # Complex reasoning → TEE +expert = "cocoon-smart" # Expert tasks → TEE +``` + +## Diagnostics + +Use the `zeph cocoon doctor` command to verify sidecar health and configuration: + +```bash +zeph cocoon doctor +``` + +Output example: + +``` +Cocoon Diagnostics +================== +Config entry: [OK] cocoon-local present in config +Sidecar reachability: [OK] http://localhost:8765/stats +Proxy connection: [OK] Direct connection established +Worker count: [OK] 4 workers available +Model listing: [OK] 7 models available +Vault key resolution: [OK] ZEPH_COCOON_CLIENT_URL resolved +``` + +### JSON Output + +For automation and scripting, use `--json`: + +```bash +zeph cocoon doctor --json +``` + +## TUI Integration + +When using the TUI dashboard with Cocoon enabled, check sidecar status and available models: + +- `/cocoon status` — Display sidecar health, worker count, and TON balance +- `/cocoon models` — List all available models on the sidecar + +Status updates automatically every 30 seconds in the background. + +## Configuration Reference + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `type` | string | — | Must be `"cocoon"` | +| `name` | string | — | Unique provider identifier | +| `base_url` | string | `"http://localhost:8765"` | Sidecar endpoint URL | +| `model` | string | — | Model name available on the sidecar | +| `stt_model` | string | (optional) | Model to use for speech-to-text | +| `cocoon_pricing` | table | (optional) | Per-1K-token pricing in cents | +| `max_tokens` | integer | 2048 | Max tokens in response | +| `temperature` | float | 0.7 | Sampling temperature | +| `top_p` | float | 1.0 | Nucleus sampling parameter | + +## Troubleshooting + +### Sidecar Not Reachable + +If you see `Cocoon: sidecar unreachable` in the TUI status bar: + +1. Verify the sidecar is running: + ```bash + curl -s http://localhost:8765/stats | jq . + ``` + +2. Check the base URL matches your sidecar port +3. Ensure network connectivity (if sidecar is on a different machine) + +### Vault Key Issues + +If `zeph cocoon doctor` reports vault key errors: + +```bash +# Set the URL in the vault +zeph vault set ZEPH_COCOON_CLIENT_URL "http://localhost:8765" + +# Verify it resolves +zeph vault get ZEPH_COCOON_CLIENT_URL +``` + +### STT Not Working + +Verify the Whisper endpoint is available on the sidecar: + +```bash +curl -s http://localhost:8765/v1/audio/transcriptions -X OPTIONS +``` + +If it returns 405 or 404, the sidecar may not have STT support compiled in. + +## See Also + +- [Audio & Vision](../advanced/multimodal.md) — Configure STT backends and vision models +- [LLM Providers](../concepts/providers.md) — Overview of all supported providers +- [Configuration Reference](../reference/configuration.md) — Full config file documentation diff --git a/book/src/guides/telegram.md b/book/src/guides/telegram.md index 9ed3f1b4f..7e49a703e 100644 --- a/book/src/guides/telegram.md +++ b/book/src/guides/telegram.md @@ -1,6 +1,6 @@ # Run via Telegram -Deploy Zeph as a Telegram bot with streaming responses, MarkdownV2 formatting, and user whitelisting. +Deploy Zeph as a Telegram bot with streaming responses, MarkdownV2 formatting, user whitelisting, and support for Guest Mode and Bot-to-Bot communication. ## Setup @@ -36,15 +36,81 @@ Deploy Zeph as a Telegram bot with streaming responses, MarkdownV2 formatting, a | `/reset` | Reset conversation context | | `/skills` | List loaded skills | -## Streaming +## Streaming and Response Updates -Telegram has API rate limits, so streaming works differently from CLI: +Telegram has API rate limits, so streaming works differently from CLI. Zeph batches response chunks and updates them on a configurable interval: - First chunk sends a new message immediately -- Subsequent chunks edit the existing message in-place (throttled to one edit per 10 seconds) +- Subsequent chunks accumulate and edit the existing message in-place +- Edit interval is configurable via `stream_interval_ms` (default 3000ms, minimum 500ms) - Long messages (>4096 chars) are automatically split - MarkdownV2 formatting is applied automatically +### Configuring Stream Interval + +Adjust the streaming update frequency to match your network conditions: + +```toml +[telegram] +stream_interval_ms = 3000 # Edit every 3 seconds (default) +# For slower connections, increase the interval: +# stream_interval_ms = 5000 # Edit every 5 seconds +# For faster feedback, decrease it: +# stream_interval_ms = 1000 # Edit every 1 second (minimum 500ms) +``` + +Lower values provide more responsive feedback but consume more API quota. Higher values reduce API calls but responses appear less fluid. Start with the default and adjust based on your network speed and API rate limit tolerance. + +## Guest Mode and Bot-to-Bot Communication + +Zeph supports advanced Telegram modes for integration with other bots and guest users. + +### Guest Mode + +Guest Mode allows Zeph to receive messages from guest users who interact via a unique link without having a Telegram account. The bot acts as a transparent proxy for guest queries: + +**Use cases:** +- Allow non-Telegram users to chat with Zeph via a web portal +- Integrate Zeph into public-facing applications +- Avoid requiring users to create Telegram accounts + +**Configuration:** + +```toml +[telegram] +guest_mode = true +``` + +When enabled, Zeph spawns a local HTTP proxy that intercepts `getUpdates` responses and extracts guest messages. Guest users see a system prompt annotation indicating their guest context, and responses are accumulated before being sent as a single reply. + +### Bot-to-Bot Communication + +Bot-to-Bot mode allows Zeph to receive and respond to messages relayed from other Telegram bots. This is useful for cascading bot workflows where one bot routes requests to Zeph for specialized processing. + +**Use cases:** +- Route specific request types from a primary bot to Zeph for expert processing +- Build bot pipelines where Zeph acts as a specialist in a workflow +- Avoid API conflicts when multiple bots are active in the same chat + +**Configuration:** + +```toml +[telegram] +bot_to_bot = true +allowed_bots = ["@specialist_bot", "@analyzer_bot"] +max_bot_chain_depth = 3 +``` + +**Fields:** + +| Field | Description | +|-------|-------------| +| `bot_to_bot` | Enable bot-to-bot mode (default: false) | +| `allowed_bots` | List of bot usernames allowed to send messages to this bot | +| `max_bot_chain_depth` | Maximum number of consecutive bot replies before cutting the chain (default: 3) | + +When enabled, Zeph registers with Telegram via `setManagedBotAccessSettings` on startup and tracks consecutive bot-to-bot reply depth to prevent circular loops. Messages from unauthorized bots are silently rejected. + ## Voice and Image Support - **Voice notes**: automatically transcribed via STT when `stt` feature is enabled diff --git a/book/src/reference/security/shadow-sentinel.md b/book/src/reference/security/shadow-sentinel.md new file mode 100644 index 000000000..e1d856a64 --- /dev/null +++ b/book/src/reference/security/shadow-sentinel.md @@ -0,0 +1,168 @@ +# ShadowSentinel: AI Safety Probing + +ShadowSentinel is a safety capability governance system that performs pre-execution LLM-based probes on high-risk tool categories before they run. It maintains a persistent audit trail of all safety events across sessions. + +**Phase 2** adds the `SafetyProbe` trait and `ShadowProbeExecutor`, enabling real-time safety classification with confidence scoring and bounded latency. + +## How It Works + +Before executing a tool, ShadowSentinel asks the LLM: "Is this tool call safe to execute?" For high-risk tool categories (shell commands, file writes, exfil-capable MCP tools), the system: + +1. Extracts tool metadata (name, arguments, category) +2. Sends a structured probe request to the configured LLM (`probe_provider`, or fallback to main provider) +3. Receives a confidence score (0.0–1.0) and reasoning +4. Logs the event to the persistent `safety_shadow_events` table +5. Allows execution if confidence > threshold (default: 0.5), or fails open if the probe times out + +The probe is **transparent** — it runs before policy gates and doesn't block concurrent tool execution. + +## Configuration + +Enable ShadowSentinel in your `config.toml`: + +```toml +[security.shadow_sentinel] +enabled = true # Enable safety probing (default: false) +probe_provider = "fast" # Optional: provider name for probing (empty = main provider) +confidence_threshold = 0.5 # Minimum confidence for approval (0.0–1.0, default: 0.5) +max_probes_per_turn = 10 # Rate limit: max probes per agent turn (default: 10) +probe_timeout_ms = 5000 # Max time for one probe (default: 5000 ms) +``` + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `enabled` | bool | false | Enable ShadowSentinel (default: false) | +| `probe_provider` | string | "" | Provider name for probes; empty uses main provider | +| `confidence_threshold` | float | 0.5 | Approval threshold (0.0–1.0); higher = stricter | +| `max_probes_per_turn` | int | 10 | Rate limit per agent turn to prevent probe spam | +| `probe_timeout_ms` | int | 5000 | Max milliseconds per probe before timeout | + +### Choosing a Probe Provider + +Probes need to be fast and inexpensive — longer latency delays tool execution. Use a fast, cheap model: + +```toml +[[llm.providers]] +name = "fast" +type = "openai" +model = "gpt-4o-mini" + +[security.shadow_sentinel] +probe_provider = "fast" # Use the cheap model for quick safety checks +``` + +When `probe_provider` is empty, ShadowSentinel falls back to the agent's main provider. + +## Probed Tool Categories + +ShadowSentinel probes are issued before executing these high-risk tool types: + +| Category | Examples | Risk Profile | +|----------|----------|--------------| +| **Shell** | `shell`, `bash`, `sh` | Arbitrary OS command execution | +| **File Write** | `write_file`, `edit_file` | Persistent state changes | +| **Exfil-capable MCP** | `brave_search`, `web_scrape` | Network access, data exfiltration | + +Tools in other categories (code execution, math, read-only file access) skip probing. + +## Safety Events Table + +Every probe is logged to the `safety_shadow_events` SQLite table (created by migration 085) for audit and analysis: + +``` +CREATE TABLE safety_shadow_events ( + id INTEGER PRIMARY KEY, + session_id TEXT NOT NULL, -- Agent session ID + timestamp TEXT NOT NULL, -- Event timestamp (ISO 8601) + tool_name TEXT NOT NULL, -- Tool being probed (e.g., "shell") + tool_args_preview TEXT, -- First 512 chars of tool args + probe_request_tokens INTEGER, -- LLM input tokens + probe_response_tokens INTEGER, -- LLM output tokens + confidence REAL, -- Safety confidence (0.0-1.0) + reasoning TEXT, -- LLM's explanation + result TEXT, -- 'approved', 'rejected', 'timeout' + execution_allowed BOOLEAN -- Whether execution proceeded +); +``` + +This allows you to: +- Audit all safety decisions across all sessions +- Analyze probe latency and cost +- Review LLM reasoning for rejected calls +- Detect patterns in tool usage and safety concerns + +### Querying Safety Events + +```bash +# Count safety events by tool +sqlite3 ~/.zeph/zeph.db "SELECT tool_name, COUNT(*) FROM safety_shadow_events GROUP BY tool_name;" + +# Find rejected probes +sqlite3 ~/.zeph/zeph.db "SELECT tool_name, confidence, reasoning FROM safety_shadow_events WHERE result = 'rejected';" + +# Recent safety events +sqlite3 ~/.zeph/zeph.db "SELECT timestamp, tool_name, confidence, result FROM safety_shadow_events ORDER BY timestamp DESC LIMIT 20;" +``` + +## Probe Behavior + +### Success (Confident Approval) + +If the probe LLM returns confidence >= `confidence_threshold`, the tool executes immediately. The event is logged with `result = 'approved'` and `execution_allowed = true`. + +### Timeout + +If the probe takes longer than `probe_timeout_ms`, ShadowSentinel fails open: the tool executes and the event is logged with `result = 'timeout'` and `execution_allowed = true`. This prevents slow probes from blocking operations. + +### Rate Limiting + +At most `max_probes_per_turn` probes are issued per agent turn. If the limit is reached, subsequent tools skip probing for that turn. This prevents probe spam when many tools are called in a single step. + +### Rejection (Low Confidence) + +When confidence < `confidence_threshold`, the tool **does not execute**. The event is logged with `result = 'rejected'` and `execution_allowed = false`. The agent receives a `ToolError::SafetyCheckFailed` result with the probe reasoning. + +The agent can acknowledge the safety concern and retry, or choose a different approach. + +## Multi-Provider Safety (Optional) + +For extra safety, probe with a different provider than the main inference engine: + +```toml +[[llm.providers]] +name = "main" +type = "openai" +model = "gpt-4-turbo" + +[[llm.providers]] +name = "safety-check" +type = "anthropic" +model = "claude-opus-4" + +[security.shadow_sentinel] +probe_provider = "safety-check" # Use Anthropic for safety, OpenAI for main inference +``` + +This creates an independent safety review layer using a different model/provider, reducing the chance of both falling into the same blind spots. + +## Disabling Probes for Specific Tools + +There is no per-tool override for probing. If you trust certain tools completely and want to skip probing: + +1. **Recommendation:** Keep probing enabled at the category level. The cost is low and the safety benefit is high. +2. **Alternative:** Disable ShadowSentinel entirely and rely on policy gates and permission checks. + +## Cost Considerations + +Each probe: +- Costs ~100 tokens prompt + ~50 tokens response (varies by tool complexity) +- At $0.0001 per 1K tokens (typical cheap models), costs ~0.015¢ per probe +- With `max_probes_per_turn = 10`, max cost per turn is ~0.15¢ + +For most workloads, probe overhead is negligible compared to main LLM inference. + +## See Also + +- [Skill Trust & Security](../../advanced/skill-trust.md) — Policy enforcement and permission models +- [File Read Sandbox](./file-sandbox.md) — Sandboxed file access restrictions +- [MCP Security](./mcp.md) — MCP server vetting and privilege isolation diff --git a/crates/zeph-channels/README.md b/crates/zeph-channels/README.md index fccb43550..1c62ce7c8 100644 --- a/crates/zeph-channels/README.md +++ b/crates/zeph-channels/README.md @@ -16,7 +16,10 @@ Implements I/O channel adapters that connect the agent to different frontends. S | Module | Description | |--------|-------------| | `cli` | `CliChannel` — interactive terminal I/O with persistent input history (rustyline), prefix search, and `/image` command for vision input | -| `telegram` | Telegram adapter via teloxide with streaming; voice/audio message detection and file download; photo message support for vision input | +| `telegram` | Telegram adapter via teloxide with streaming; voice/audio message detection and file download; photo message support for vision input; configurable streaming edit interval (`stream_interval_ms`, default 3000 ms, minimum 500 ms) | +| `telegram::guest` | Guest Mode — transparent local axum HTTP proxy that intercepts `getUpdates` responses and surfaces `guest_message` entries (Bot API 10.0) without a second `getUpdates` connection | +| `telegram::bot_to_bot` | Bot-to-Bot communication — registers via `setManagedBotAccessSettings` on startup; per-chat reply-depth tracking via `BotReplyCounters`; configurable `max_bot_chain_depth` | +| `telegram::api` | `TelegramApiClient` — raw HTTP wrapper for Bot API 10.0 methods unavailable in teloxide 0.17: `answer_guest_query`, `get/set_managed_bot_access_settings`, `delete_message_reaction`, `delete_all_message_reactions` | | `discord` | Discord adapter (optional feature) | | `slack` | Slack adapter (optional feature); audio file detection and download with Bearer auth | | `any` | `AnyChannel` — enum dispatch over all channels | @@ -27,6 +30,30 @@ Implements I/O channel adapters that connect the agent to different frontends. S > [!NOTE] > `ChannelError` is defined in `zeph-core::channel` and used directly by all channel adapters. `zeph-channels` does not re-export it. +## Telegram configuration + +Key fields in the `[telegram]` config section: + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `stream_interval_ms` | u64 | `3000` | Minimum interval between streaming message edits (minimum 500 ms) | +| `guest_mode` | bool | `false` | Enable Bot API 10.0 Guest Mode — surfaces guest messages via a local proxy | +| `bot_to_bot` | bool | `false` | Enable Bot-to-Bot communication via `setManagedBotAccessSettings` | +| `allowed_bots` | `Vec` | `[]` | Telegram user IDs of bots allowed to interact with this agent | +| `max_bot_chain_depth` | usize | `3` | Max consecutive bot replies before the chain is suppressed | + +```toml +[telegram] +stream_interval_ms = 3000 +guest_mode = false +bot_to_bot = false +allowed_bots = [] +max_bot_chain_depth = 3 +``` + +> [!NOTE] +> Guest Mode spawns a local axum HTTP proxy on an ephemeral port. Bot API 10.0 is required; ensure your bot account has access to guest message updates. + ## Features | Feature | Description | diff --git a/crates/zeph-core/README.md b/crates/zeph-core/README.md index bcd5bb2fc..4ab5021f9 100644 --- a/crates/zeph-core/README.md +++ b/crates/zeph-core/README.md @@ -43,6 +43,7 @@ Core orchestration crate for the Zeph agent. Manages the main agent loop, bootst | `skill_loader` | `SkillLoaderExecutor` — `ToolExecutor` that exposes the `load_skill` tool to the LLM; accepts a skill name, looks it up in the shared `Arc>`, and returns the full SKILL.md body (truncated to `MAX_TOOL_OUTPUT_CHARS`); skill name is capped at 128 characters; unknown names return a human-readable error message rather than a hard error | | `skill_invoke` | `SkillInvokeExecutor` — `ToolExecutor` that exposes the `invoke_skill` tool with trust-aware sanitization; Blocked skills are refused; non-Trusted bodies pass through `sanitize_skill_text`; Quarantined bodies are additionally wrapped with `wrap_quarantined`; exempt from adversarial policy, VIGIL gate, and tool-schema filter | | `vigil` | `VigilGate` — regex tripwire that runs before `ContentSanitizer` on every tool output; configurable via `[security.vigil]`; `VigilRiskLevel` recorded in audit entries; `vigil_flags_total` / `vigil_blocks_total` counters in `MetricsSnapshot`; fail-open on invalid config; subagent sessions exempt | +| `security::shadow_sentinel` | ShadowSentinel Phase 2 — `ShadowProbeExecutor` wraps the tool executor chain between `ScopedToolExecutor` and `PolicyGateExecutor`; issues pre-execution LLM probes (`SafetyProbe` trait, `LlmSafetyProbe` impl) before high-risk tool categories (shell, file write, exfil-capable MCP); results persisted in `safety_shadow_events` SQLite table (migration 085) for cross-session safety audit; fail-open by default; bounded by `max_probes_per_turn` and `probe_timeout_ms`; enabled via `[security.shadow_sentinel]` | | `scheduler_executor` | `SchedulerExecutor` — `ToolExecutor` that exposes three LLM-callable tools: `schedule_periodic` (add a recurring cron task), `schedule_deferred` (add a one-shot task at a specific ISO 8601 UTC time), and `cancel_task` (remove a task by name); communicates with the scheduler via `mpsc::Sender` and validates input lengths and cron expressions before forwarding; only present when the `scheduler` feature is enabled | | `debug_dump` | `DebugDumper` — writes numbered `{id:04}-request.json`, `{id:04}-response.txt`, and `{id:04}-tool-{name}.txt` files to a timestamped session directory; request dumps include model, token limit, tools, temperature, cache metadata, and message payloads in both `json` and `raw` formats; enabled via `--debug-dump [PATH]` CLI flag, `[debug] enabled = true` config, or `/debug-dump [path]` slash command; hooks into both streaming and non-streaming LLM paths and before `maybe_summarize_tool_output` | | `agent::log_commands` | `/log` slash command handler — displays current `LoggingConfig` (file path, level, rotation, max files) and tails the last 20 lines from the active log file | @@ -368,6 +369,20 @@ timeout_ms = 2000 `GoalLifecycle` tracks active goals across turns. Tool outputs for completed or stale goals are compressed by the TACO (Tool-Aware Compaction Optimization) pipeline, which archives bodies to SQLite before the LLM compaction call and injects UUID back-references into the resulting summary. +## ShadowSentinel safety probes + +`ShadowSentinel` (`[security.shadow_sentinel]`) intercepts high-risk tool calls before execution and issues a pre-execution LLM safety probe. Probe outcomes are recorded in the `safety_shadow_events` SQLite table, forming a persistent cross-session safety audit trail. + +```toml +[security.shadow_sentinel] +enabled = false # opt-in (default: false) +max_probes_per_turn = 5 # max LLM probes issued per agent turn +probe_timeout_ms = 2000 # per-probe timeout; fail-open on expiry +``` + +> [!NOTE] +> ShadowSentinel is fail-open by default — a timed-out or failed probe does not block execution. Set `fail_closed = true` to block tool calls when the probe cannot complete within `probe_timeout_ms`. + ## Reactive hooks `[hooks]` in `config.toml` defines shell commands that fire on working-directory or file-change events. Hooks are now traced with `tracing` instrumentation and are propagated correctly through `reload_config` — hooks registered after a live config reload fire identically to those present at startup. @@ -389,6 +404,24 @@ The `set_working_directory` tool is exposed to the LLM and updates the agent's c | `ZEPH_OLD_CWD` | `cwd_changed` | Previous working directory | | `ZEPH_NEW_CWD` | `cwd_changed` | New working directory | | `ZEPH_CHANGED_PATH` | `file_changed` | Absolute path of the changed file | +| `ZEPH_TOOL_NAME` | `pre_tool_use`, `post_tool_use` | Name of the tool being called | +| `ZEPH_TOOL_ARGS_JSON` | `pre_tool_use`, `post_tool_use` | JSON-encoded tool arguments (truncated at 64 KiB) | +| `ZEPH_SESSION_ID` | `pre_tool_use`, `post_tool_use` | Session ID (main agent only; omitted in sub-agents) | +| `ZEPH_TOOL_DURATION_MS` | `post_tool_use` | Tool execution duration in milliseconds | + +`[[hooks.pre_tool_use]]` and `[[hooks.post_tool_use]]` accept `HookMatcher` entries with pipe-separated tool name patterns. `pre_tool_use` fires before the `RuntimeLayer` permission check so observers see all attempted calls. + +```toml +[[hooks.pre_tool_use]] +match = "shell|bash" +command = "echo tool=$ZEPH_TOOL_NAME args=$ZEPH_TOOL_ARGS_JSON" +timeout_secs = 5 + +[[hooks.post_tool_use]] +match = "*" +command = "echo finished $ZEPH_TOOL_NAME in ${ZEPH_TOOL_DURATION_MS}ms" +timeout_secs = 5 +``` ## Features diff --git a/crates/zeph-memory/README.md b/crates/zeph-memory/README.md index b72d29abb..ff4f8cd07 100644 --- a/crates/zeph-memory/README.md +++ b/crates/zeph-memory/README.md @@ -317,6 +317,8 @@ The `graph` module provides SQLite-backed entity-relationship tracking: - **Embedding-based entity resolution** — when `use_embedding_resolution = true`, entities are deduplicated via cosine similarity in Qdrant with a two-threshold approach (auto-merge at >= 0.85, LLM disambiguation at >= 0.70, new entity below); integrated after alias and canonical-name lookup steps; falls back to create-new on failure - **APEX-MEM append-only property graph** — migration 075 adds a `supersedes` column (append-only pointer to the prior head edge) and a `canonical_relation` column (normalized predicate). Superseded edges are never deleted; `insert_or_supersede` atomically creates the new head and links it to the prior. `check_supersede_depth` (recursive CTE, depth-capped at `SUPERSEDE_DEPTH_CAP`) detects runaway supersession chains. `OntologyTable` (ArcSwap + LRU-4096 cache) normalizes relation predicates with LLM fallback. `ConflictResolver` resolves contradictory edges via `recency`, `confidence`, or `llm` strategy. The `edge_reassertions` table records byte-identical reassertions for provenance. +**BeliefMem probabilistic edge layer** — migration 084 adds `pending_beliefs` and `belief_evidence` tables that accumulate candidate facts with probability weights before committing them as APEX-MEM edges. Evidence is combined via Noisy-OR with optional temporal decay (`belief_decay_rate`). A belief is promoted to a committed edge when `max(prob) >= promote_threshold` (default 0.85). Uncertainty-preserving retrieval returns top-K candidates when no committed edge exists. Enabled via `[memory.graph.belief_mem]` (opt-in, default off). + `GraphStore` provides CRUD methods over five SQLite tables (`graph_entities`, `graph_entity_aliases`, `graph_edges`, `graph_communities`, `graph_metadata`). Schema is created by migrations 021, 023, and 024. `SemanticMemory::spawn_graph_extraction()` runs LLM-powered extraction as a fire-and-forget background task with configurable timeout. `recall_graph()` performs fuzzy entity matching plus BFS edge traversal, returning composite-scored `GraphFact` values for context injection. @@ -350,6 +352,20 @@ timeout_ms = 500 # Activation timeout to prevent runaway trav recall_timeout_ms = 1000 # Timeout for the full graph recall call (default: 1000) ``` +## BeliefMem probabilistic edges + +`BeliefMem` (`[memory.graph.belief_mem]`) stages candidate graph facts as probabilistic beliefs before committing them as permanent APEX-MEM edges. Evidence from multiple turns accumulates via Noisy-OR, and facts are only committed when confidence exceeds the promotion threshold. + +```toml +[memory.graph.belief_mem] +enabled = false # opt-in (default: false) +promote_threshold = 0.85 # min probability to commit a belief as an APEX-MEM edge +belief_decay_rate = 0.0 # temporal decay applied to evidence weights (0.0 = disabled) +``` + +> [!TIP] +> Enable BeliefMem when the agent frequently extracts facts from uncertain or contradictory sources. Beliefs that never reach the threshold are discarded rather than polluting the committed graph. + ## MemCoT semantic state accumulation `SemanticStateAccumulator` tracks entity salience and relationship density across turns, maintaining a rolling cognitive thread. Two recall views are supported: diff --git a/crates/zeph-tui/src/widgets/snapshots/zeph_tui__widgets__splash__tests__splash_default.snap b/crates/zeph-tui/src/widgets/snapshots/zeph_tui__widgets__splash__tests__splash_default.snap index 1b6e3901f..be890c855 100644 --- a/crates/zeph-tui/src/widgets/snapshots/zeph_tui__widgets__splash__tests__splash_default.snap +++ b/crates/zeph-tui/src/widgets/snapshots/zeph_tui__widgets__splash__tests__splash_default.snap @@ -1,6 +1,5 @@ --- source: crates/zeph-tui/src/widgets/splash.rs -assertion_line: 79 expression: output --- ┌──────────────────────────────────────────────────────────┐ @@ -15,7 +14,7 @@ expression: output │ ███████╗███████╗██║ ██║ ██║ │ │ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ │ │ │ -│ v0.20.2 │ +│ v0.21.0 │ │ │ │ Type a message to start. │ │ │ diff --git a/specs/004-memory/004-7-memory-apex-magma.md b/specs/004-memory/004-7-memory-apex-magma.md index 31a921873..c2ea6ad34 100644 --- a/specs/004-memory/004-7-memory-apex-magma.md +++ b/specs/004-memory/004-7-memory-apex-magma.md @@ -572,7 +572,7 @@ OCR-Memory renders agent trajectories as annotated images and uses a locate-and- ## §16 BeliefMem: Pre-Commitment Probabilistic Edge Layer **Tracking issue**: #3706 -**Status**: Implemented (PR pending) +**Status**: Implemented (PR #3735, merged 2026-05-10) **Module**: `crates/zeph-memory/src/graph/belief.rs` ### 16.1 Overview @@ -634,11 +634,11 @@ Both functions are pure and exported from `zeph_memory::graph::belief`: ### 16.8 Acceptance Criteria -- [ ] `pending_beliefs` and `belief_evidence` tables created by migration 084. -- [ ] `BeliefStore::record_evidence` applies temporal decay + Noisy-OR and returns `Some(PendingBelief)` when `prob >= promote_threshold`. -- [ ] `BeliefStore::retrieve_candidates` returns beliefs ordered by `prob DESC` with correct `top_k`. -- [ ] `BeliefStore::mark_promoted` sets `promoted_at` and `promoted_edge_id`. -- [ ] `BeliefStore::evict_stale` deletes rows exceeding `max_candidates_per_group`. -- [ ] `ExtractedEdge::confidence` is populated by the LLM extraction prompt. -- [ ] All pure functions (`noisy_or`, `time_decayed_prob`) have passing unit tests. -- [ ] `cargo build -p zeph-memory` and `cargo clippy -p zeph-memory -- -D warnings` pass. +- [x] `pending_beliefs` and `belief_evidence` tables created by migration 084. +- [x] `BeliefStore::record_evidence` applies temporal decay + Noisy-OR and returns `Some(PendingBelief)` when `prob >= promote_threshold`. +- [x] `BeliefStore::retrieve_candidates` returns beliefs ordered by `prob DESC` with correct `top_k`. +- [x] `BeliefStore::mark_promoted` sets `promoted_at` and `promoted_edge_id`. +- [x] `BeliefStore::evict_stale` deletes rows exceeding `max_candidates_per_group`. +- [x] `ExtractedEdge::confidence` is populated by the LLM extraction prompt. +- [x] All pure functions (`noisy_or`, `time_decayed_prob`) have passing unit tests. +- [x] `cargo build -p zeph-memory` and `cargo clippy -p zeph-memory -- -D warnings` pass. diff --git a/specs/007-channels/007-1-telegram-guest-mode.md b/specs/007-channels/007-1-telegram-guest-mode.md index 2d2cf6c1c..6fb7924a0 100644 --- a/specs/007-channels/007-1-telegram-guest-mode.md +++ b/specs/007-channels/007-1-telegram-guest-mode.md @@ -10,7 +10,7 @@ tags: - telegram - bot-api-10 created: 2026-05-10 -status: approved +status: implemented related: - "[[007-channels/spec]]" - "[[007-channels/007-2-telegram-bot-to-bot]]" @@ -319,18 +319,18 @@ guest-message authorization — no new field is needed. --- -## 15. Acceptance Criteria (Issue #3729) - -- [ ] `telegram.guest_mode = false` disables the handler; bot ignores guest mentions -- [ ] `telegram.guest_mode = true` registers handler; bot responds to @mentions -- [ ] `allowed_users` check applied to `guest_bot_caller_user` before LLM call -- [ ] Response routed through `answerGuestQuery`, not `sendMessage` -- [ ] No `editMessageText` calls when `guest_query_id` is present -- [ ] System prompt annotated with guest context string -- [ ] `is_guest_context: bool` available on `ChannelMessage` -- [ ] `guest_query_id: Option` added to `IncomingMessage` -- [ ] Unit tests: authorization pass, authorization fail, routing, config parsing -- [ ] Live test: @mention bot in a group, verify response reaches caller +## 15. Acceptance Criteria (Issue #3729) — Implemented in PR #3748 + +- [x] `telegram.guest_mode = false` disables the handler; bot ignores guest mentions +- [x] `telegram.guest_mode = true` registers handler; bot responds to @mentions +- [x] `allowed_users` check applied to `guest_bot_caller_user` before LLM call +- [x] Response routed through `answerGuestQuery`, not `sendMessage` +- [x] No `editMessageText` calls when `guest_query_id` is present +- [x] System prompt annotated with guest context string +- [x] `is_guest_context: bool` available on `ChannelMessage` +- [x] `guest_query_id: Option` added to `IncomingMessage` +- [x] Unit tests: authorization pass, authorization fail, routing, config parsing +- [ ] Live test: @mention bot in a group, verify response reaches caller (pending live session) - [ ] Playbook updated: `.local/testing/playbooks/telegram.md` - [ ] Coverage-status updated diff --git a/specs/007-channels/007-2-telegram-bot-to-bot.md b/specs/007-channels/007-2-telegram-bot-to-bot.md index eae4064e6..afa18439d 100644 --- a/specs/007-channels/007-2-telegram-bot-to-bot.md +++ b/specs/007-channels/007-2-telegram-bot-to-bot.md @@ -11,7 +11,7 @@ tags: - bot-api-10 - multi-agent created: 2026-05-10 -status: approved +status: implemented related: - "[[007-channels/spec]]" - "[[007-channels/007-1-telegram-guest-mode]]" @@ -376,18 +376,18 @@ max_bot_chain_depth = 3 --- -## 15. Acceptance Criteria (Issue #3730) - -- [ ] `bot_to_bot = false` (default): bot ignores messages from other bots (existing behavior preserved) -- [ ] `bot_to_bot = true`: bot responds to bots in `allowed_bots` (or all bots if list is empty) -- [ ] `setManagedBotAccessSettings` called at startup when `bot_to_bot = true` -- [ ] `setManagedBotAccessSettings` NOT called when `bot_to_bot = false` -- [ ] Reply chain depth tracked; responses dropped when depth ≥ `max_bot_chain_depth` -- [ ] Warn log emitted when message dropped due to depth limit (includes depth, message ID, sender) -- [ ] `is_from_bot` field available on `ChannelMessage` -- [ ] `is_from_bot` field available on `IncomingMessage` -- [ ] Unit tests: `bot_to_bot = false` drops, authorization pass, authorization fail, depth 0 processes, depth N-1 processes, depth N drops, `max_bot_chain_depth = 0` drops all -- [ ] Live test: two bot instances communicate; loop terminates after `max_bot_chain_depth` +## 15. Acceptance Criteria (Issue #3730) — Implemented in PR #3748 + +- [x] `bot_to_bot = false` (default): bot ignores messages from other bots (existing behavior preserved) +- [x] `bot_to_bot = true`: bot responds to bots in `allowed_bots` (or all bots if list is empty) +- [x] `setManagedBotAccessSettings` called at startup when `bot_to_bot = true` +- [x] `setManagedBotAccessSettings` NOT called when `bot_to_bot = false` +- [x] Reply chain depth tracked; responses dropped when depth ≥ `max_bot_chain_depth` +- [x] Warn log emitted when message dropped due to depth limit (includes depth, message ID, sender) +- [x] `is_from_bot` field available on `ChannelMessage` +- [x] `is_from_bot` field available on `IncomingMessage` +- [x] Unit tests: `bot_to_bot = false` drops, authorization pass, authorization fail, depth 0 processes, depth N-1 processes, depth N drops, `max_bot_chain_depth = 0` drops all +- [ ] Live test: two bot instances communicate; loop terminates after `max_bot_chain_depth` (pending live session) - [ ] Playbook updated: `.local/testing/playbooks/telegram.md` - [ ] Coverage-status updated diff --git a/specs/007-channels/spec.md b/specs/007-channels/spec.md index 8ad1c9788..d2423cfef 100644 --- a/specs/007-channels/spec.md +++ b/specs/007-channels/spec.md @@ -32,6 +32,7 @@ related: |---|---| | `crates/zeph-core/src/channel.rs` | `Channel` trait, `ChannelMessage`, `ChannelError` | | `crates/zeph-channels/src/any.rs` | `AnyChannel` enum, `dispatch_channel!` macro | +| `crates/zeph-channels/src/telegram_api_ext.rs` | `TelegramApiClient` — raw HTTP wrapper for Bot API 10.0 methods absent from teloxide 0.17 | | `crates/zeph-tui/src/channel.rs` | `TuiChannel` implementation | --- @@ -187,6 +188,38 @@ Discord channel registers slash commands (`/reset`, `/skills`, `/agent`) at star --- +## TelegramApiClient — Raw HTTP Wrapper (Bot API 10.0) + +Issue #3728. `crates/zeph-channels/src/telegram_api_ext.rs`. + +`teloxide` 0.17 does not expose methods introduced in Bot API 10.0. `TelegramApiClient` +is a thin `reqwest`-based raw HTTP client that covers these gap methods. + +### Covered methods + +| Method | Description | +|--------|-------------| +| `answer_guest_query(query_id, text, parse_mode)` | Respond to a `guest_message` update | +| `get_managed_bot_access_settings()` | Read current `BotAccessSettings` | +| `set_managed_bot_access_settings(settings)` | Enable/disable bot-to-bot messaging | +| `delete_message_reaction(chat_id, message_id)` | Remove a bot's reaction | +| `delete_all_message_reactions(chat_id, message_id)` | Remove all reactions from a message | + +### Design invariants + +- Bot token is redacted in `Debug` output and stripped from `reqwest` errors via `.without_url()` +- All API calls share a single `#[tracing::instrument]` on the `post()` helper +- `TelegramApiClient` is injected into `TelegramChannel` at construction; callers do not + instantiate it directly + +### Key Invariants + +- NEVER expose the bot token in `Debug`, `Display`, or log output +- All methods must go through the shared `post()` helper — no ad-hoc `reqwest::Client` calls +- New Bot API 10.0 methods that require raw HTTP must be added here, not as teloxide patches + +--- + ## Telegram Bot API 10.0 Extensions Sub-specs for Telegram Bot API 10.0 features live in this directory: diff --git a/specs/028-hooks/spec.md b/specs/028-hooks/spec.md index 53f6fb954..ad434c8b6 100644 --- a/specs/028-hooks/spec.md +++ b/specs/028-hooks/spec.md @@ -45,6 +45,7 @@ agent lifecycle events. Five event types are supported: | `file_changed` | A watched file or directory subtree is modified on disk | | `permission_denied` | A tool execution is short-circuited by a `RuntimeLayer::before_tool` check | | `turn_complete` | An agent turn completes (after all tool calls and LLM response) | +| `pre_tool_use` | Before any LLM-requested tool invocation — fires before the utility gate and `RuntimeLayer::before_tool` check (#3725) | | `post_tool_use` | After any tool invocation completes (carries `ZEPH_TOOL_DURATION_MS`) | Hooks are defined as arrays under `[hooks]` in `config.toml`. Each entry specifies @@ -78,6 +79,10 @@ command = "echo 'tool $ZEPH_DENIED_TOOL blocked: $ZEPH_DENY_REASON'" type = "command" command = "osascript -e 'display notification \"$ZEPH_TURN_PREVIEW\" with title \"Zeph\"'" +[[hooks.pre_tool_use]] +type = "command" +command = "echo 'about to call $ZEPH_TOOL_NAME'" + [[hooks.post_tool_use]] type = "command" command = "echo 'tool took ${ZEPH_TOOL_DURATION_MS}ms'" @@ -126,6 +131,9 @@ Hooks receive context via environment variables injected into the shell command: | `ZEPH_TURN_STATUS` | `turn_complete` | `"success"` or `"error"` | | `ZEPH_TURN_PREVIEW` | `turn_complete` | Redacted short preview of the LLM response | | `ZEPH_TURN_LLM_REQUESTS` | `turn_complete` | Number of LLM requests in the turn | +| `ZEPH_TOOL_NAME` | `pre_tool_use`, `post_tool_use` | Name of the tool being invoked | +| `ZEPH_TOOL_ARGS_JSON` | `pre_tool_use`, `post_tool_use` | JSON-serialized tool arguments, truncated to 64 KiB at a valid UTF-8 char boundary | +| `ZEPH_SESSION_ID` | `pre_tool_use`, `post_tool_use` | Session identifier (main agent path only; absent in subagent path) | | `ZEPH_TOOL_DURATION_MS` | `post_tool_use` | Wall-clock duration of the tool call in milliseconds | > [!note] `turn_complete` gate @@ -239,6 +247,9 @@ validating the new config. `HookRunner::replace_config` is an atomic swap using - `turn_complete` is added to `HooksConfig` and `HooksConfig::is_empty()` check (#3327) - `type = "mcp_tool"` action requires MCP manager active; must fail gracefully per `fail_closed` setting when unavailable (#3293) - `HookRunner` uses `ArcSwap` — live reload is atomic, no lock contention on hook dispatch +- `pre_tool_use` fires for ALL LLM-requested tool calls including those intercepted by the utility gate (Retrieve/Verify/Stop) — dispatch is ordered **before** `check_call_gates` in `build_tier_call_futures` (#3738); internal tools (`compress_context`, `start_focus`, `complete_focus`) are excluded via the early-continue guard +- `post_tool_use` fires after every tool invocation via `apply_tier_results`, matching `pre_tool_use` symmetry +- `pre_tool_use` hook failures are fail-open: a non-zero exit aborts the hook chain but does NOT block the tool call - NEVER inject hook stdout into the agent's conversation context - NEVER run hooks with elevated privileges — they inherit the agent process permissions only - If `[hooks]` section is absent from config, all hook lists are empty and no hooks fire — zero-cost when unused diff --git a/specs/050-security-capability-governance/spec.md b/specs/050-security-capability-governance/spec.md index f1bbee4f1..021c4eb94 100644 --- a/specs/050-security-capability-governance/spec.md +++ b/specs/050-security-capability-governance/spec.md @@ -717,7 +717,7 @@ are not rediscovered as bugs: --- -## Phase 2: ShadowSentinel SafetyProbe (implemented 2026-05-10) +## Phase 2: ShadowSentinel SafetyProbe (PR #3735 + #3739 + #3742 + #3745, merged 2026-05-10) ### Overview @@ -737,6 +737,14 @@ for every structured tool call (`execute_tool_call` / `execute_tool_call_confirm The legacy fenced-block path (`execute`) bypasses the probe — no structured tool id is available there. +**Wiring implementation (#3742).** `ShadowSentinel` and `ShadowProbeExecutor` are +instantiated in `src/runner.rs` when `config.security.shadow_sentinel.enabled = true`. +A `ShadowSentinelProbeGateAdapter` bridges `ProbeVerdict` (returned by `zeph-core`) and +`ProbeOutcome` (consumed by `zeph-tools`) without introducing a circular crate dependency. +`shadow_sentinel` is added as a field on `SecurityState` with a `with_shadow_sentinel()` +builder method. `sentinel.advance_turn()` is called in `begin_turn()` in the agent loop, +ordered before gate evaluation (preserving the `TrajectorySentinel` invariant). + ### New components | Component | Crate | File | @@ -824,12 +832,37 @@ probe_patterns = ["builtin:shell*", "builtin:write", "builtin:edit", "mcp:*/file deny_on_timeout = false ``` +### `classify_tool` fast-path — bare tool IDs (fix #3744) + +`ShadowSentinel::classify_tool` originally checked only qualified ids +(`"builtin:bash"`, `"builtin:shell"`) but `ShellExecutor` and `FileExecutor` +register their tools **without** the `"builtin:"` prefix. As a result, +`classify_tool("bash")` returned `ToolRiskCategory::Low` and +`ProbeVerdict::Skip`, so the LLM safety probe never fired for any shell +execution. + +The fast-path now covers both forms: + +| Input | Category | +|-------|----------| +| `"bash"`, `"shell"`, `"sh"`, `"builtin:bash"`, `"builtin:shell"`, `"builtin:sh"` | `Shell` | +| `"write"`, `"edit"`, `"delete"`, `"builtin:write"`, `"builtin:edit"`, `"builtin:delete"` | `FileWrite` | +| Anything matching `probe_patterns` globs | `ExfilCapable` or per-pattern category | +| Anything else | `Low` | + +**Key invariant**: the fast-path bare-name entries MUST stay in sync with +the actual tool IDs registered by `ShellExecutor` and `FileExecutor`. When +either executor renames a tool, `classify_tool` must be updated in the same +PR. A unit test enumerates `ShellExecutor::tool_definitions()` and asserts +each id maps to `Shell` or `FileWrite` as appropriate. + ### Acceptance criteria - `ShadowProbeExecutor`: Allow/Skip → delegate to inner; Deny → `ToolError::SafetyDenied`. - Legacy `execute()` path always bypasses the probe. - `is_tool_speculatable` returns `false` for all tool ids. -- `ShadowSentinel::classify_tool`: `builtin:shell/bash` → `Shell`; `builtin:write/edit` → `FileWrite`; unmatched → `Low`. +- `ShadowSentinel::classify_tool`: `"bash"` → `Shell`; `"builtin:bash"` → `Shell`; `"write"` → `FileWrite`; `"builtin:write"` → `FileWrite`; unmatched → `Low`. +- `classify_tool` fast-path covers both bare and qualified ids for shell and file-write tools. - `advance_turn()` resets `probes_this_turn` to 0. - `parse_verdict`: `{"verdict":"allow"}` → Allow; `{"verdict":"deny","reason":"..."}` → Deny; unparseable → Allow (fail-open). - All unit tests pass. clippy `-D warnings` clean. fmt check passes. diff --git a/specs/README.md b/specs/README.md index 094b49920..776705fe8 100644 --- a/specs/README.md +++ b/specs/README.md @@ -39,7 +39,7 @@ Spec IDs (001–044) follow a logical grouping: - **047**: CLI execution modes (--bare, --json, -y, /loop, /recap) - **048**: SLM cost metrics survey and CPS metric contract - **049**: Agent god-object decomposition (Services aggregator + AgentRuntime newtype) -- **050**: Security capability governance (tool scoping + trajectory sentinel + CapSeal sketch) +- **050**: Security capability governance (tool scoping + trajectory sentinel + Phase 2 ShadowSentinel safety probe + classify_tool bare-ID fix + CapSeal sketch) [Phase 1+2 implemented] - **051**: Gonka.ai Phase 1 — GonkaGate hosted gateway (CompatibleProvider, wizard, vault key) [implemented] - **052**: Gonka.ai Phase 2 — native network transport (GonkaProvider, ECDSA signing, EndpointPool, chat_with_tools, chat_typed) [implemented] - **053**: SpeculationEngine — speculative tool execution (SSE decoding path, PASTE skill activation, ToolStartEvent{speculative:true}) @@ -68,7 +68,7 @@ Spec IDs (001–044) follow a logical grouping: | `002-agent-loop/spec.md` | Agent loop, turn lifecycle, context pressure, HiAgent subgoal-aware compaction | `zeph-core` | | `003-llm-providers/spec.md` | LlmProvider trait, AnyProvider, prompt caching, configurable `CacheTtl` (ephemeral/1h) | `zeph-llm` | | `004-memory/spec.md` | SQLite + Qdrant, compaction, semantic response cache, anchored summarization, compaction probe, importance scoring, A-MAC admission control, MemScene consolidation, multi-vector chunking, GAAMA episode nodes, BATS budget hints, Focus compression, SleepGate forgetting pass, persona memory, trajectory memory, category-aware memory, TiMem tree, microcompact, autoDream, MagicDocs, embed backfill batching | `zeph-memory` | -| `004-memory/004-7-memory-apex-magma.md` | APEX-MEM append-only MAGMA: edge supersession, ontology normalization, SYNAPSE conflict resolution (#3223) | `zeph-memory` | +| `004-memory/004-7-memory-apex-magma.md` | APEX-MEM append-only MAGMA: edge supersession, ontology normalization, SYNAPSE conflict resolution (#3223); BeliefMem probabilistic pre-commitment edge layer with Noisy-OR accumulation, temporal decay, promotion threshold (#3706) | `zeph-memory` | | `004-memory/004-8-memory-typed-pages.md` | ClawVM typed page compaction: PageType classification, minimum-fidelity invariants, compaction audit log (#3221) | `zeph-context`, `zeph-memory` | | `004-memory/004-9-memory-write-gate.md` | MemReader write quality gate: three-signal scorer, rule-based MVP, optional LLM scoring (#3222) | `zeph-memory` | | `004-memory/004-10-memory-memmachine-retrieval.md` | MemMachine retrieval-depth-first memory: retrieval depth config, search prompt templates, query bias correction, episode preservation (#3325) | `zeph-memory` | @@ -103,7 +103,7 @@ Spec IDs (001–044) follow a logical grouping: | `025-classifiers/spec.md` | Candle-backed ML classifiers: injection detection, PII detection, LlmClassifier for feedback, unified regex+NER sanitization pipeline | `zeph-classifiers` | | `026-tui-subagent-management/spec.md` | Interactive TUI subagent sidebar (a key), j/k navigation, Enter loads transcript, Esc returns, Tab cycling | `zeph-tui` | | `027-runtime-layer/spec.md` | RuntimeLayer middleware with before_chat/after_chat/before_tool/after_tool hooks, NoopLayer, LayerContext, unwind guards; plugin config overlay merge (tighten-only) | `zeph-core` | -| `028-hooks/spec.md` | Reactive hooks: cwd_changed / file_changed events, set_working_directory tool, FileChangeWatcher, ZEPH_* env vars | `zeph-core` | +| `028-hooks/spec.md` | Reactive hooks: cwd_changed / file_changed / permission_denied / turn_complete / pre_tool_use / post_tool_use events, set_working_directory tool, FileChangeWatcher, ZEPH_TOOL_NAME / ZEPH_TOOL_ARGS_JSON / ZEPH_SESSION_ID env vars (#3725); pre_tool_use fires before utility gate (#3738) | `zeph-core` | | `029-feature-flags/spec.md` | Feature flag decision rules, surviving flag inventory (22 flags), bundle definitions (desktop, ide, server, full) | `Cargo.toml`, cross-cutting | | `030-tui-slash-autocomplete/spec.md` | Inline autocomplete dropdown in TUI Insert mode, reuses filter_commands registry, Tab/Enter accepts, Esc dismisses | `zeph-tui` | | `031-database-abstraction/spec.md` | PostgreSQL backend, zeph-db crate, DatabaseDriver trait, Dialect trait, sql!() macro, migrations, CLI subcommands | `zeph-db`, cross-cutting | @@ -127,7 +127,7 @@ Spec IDs (001–044) follow a logical grouping: | `UX/mention-routing.md` | @agent mention routing: Goose pattern analysis, feasibility for Zeph TUI/A2A, verdict to defer pending `AgentRegistry` infrastructure (#3327) | `zeph-core`, `zeph-tui`, `zeph-a2a` | | `048-slm-cost-metrics/spec.md` | SLM survey findings (arXiv:2510.03847), CPS (cost per successful task) metric contract, `record_successful_task()` / `cps()` API, daily reset semantics | `zeph-core` | | `049-agent-decomposition/spec.md` | Agent god-object Phase 2 (#3509): split `Agent` 25+ direct sub-state fields into `services: Services` (background subsystems) and `runtime: AgentRuntime` (config, lifecycle, providers, metrics, debug, instructions); pure refactor, no API change, separately borrowable; `TurnContext` boundary sketched for P2-prereq-3 | `zeph-core` | -| `050-security-capability-governance/spec.md` | Capability scoping (`ScopedToolExecutor` + per-task-type allow-lists, #3563), `TrajectorySentinel` multi-turn risk accumulator with decay (#3570), and CapSeal/SUDP `VaultBroker::propose_operation` Phase-3 research sketch (#3569) | `zeph-tools`, `zeph-core` | +| `050-security-capability-governance/spec.md` | Capability scoping (`ScopedToolExecutor` + per-task-type allow-lists, #3563), `TrajectorySentinel` multi-turn risk accumulator with decay (#3570), Phase 2: `ShadowSentinel` safety probe — `SafetyProbe` trait, `LlmSafetyProbe`, `ShadowProbeExecutor`, `safety_shadow_events` table, `classify_tool` bare-ID fix (#3705, #3735, #3739, #3742, #3744, #3745), CapSeal/SUDP `VaultBroker::propose_operation` Phase-3 research sketch (#3569) | `zeph-tools`, `zeph-core` | | `051-gonka-gateway/spec.md` | Phase 1: gonka.ai inference via GonkaGate hosted gateway — zero new Rust code, `CompatibleProvider` reuse, wizard branch, vault key `ZEPH_COMPATIBLE_GONKAGATE_API_KEY` | `zeph-llm`, `zeph-config` | | `052-gonka-native/spec.md` | Phase 2: native gonka network transport — `GonkaProvider`, ECDSA secp256k1 signing (`RequestSigner`), `EndpointPool` round-robin fail-skip, `send_signed_with_retry`, `chat_with_tools`, `chat_typed`, `zeph gonka doctor` | `zeph-llm`, `zeph-config` | | `053-speculation-engine/spec.md` | `SpeculationEngine` — speculative tool execution: `PartialJsonParser` SSE decoding path, PASTE skill activation, `try_dispatch`/`try_commit`/`end_turn` API, `ToolStartEvent{speculative:true}`, `DynExecutor` confirmation delegation | `zeph-core`, `zeph-tools` | From bede23f846e0997f4dfea4658427c51c95860eb0 Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:21:50 +0200 Subject: [PATCH 2/6] docs(readme): rewrite distributed inference section to be provider-agnostic --- README.md | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 820ae7abe..f5e0c0405 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Unlike single-session assistants, Zeph is designed to remember *why* a decision | An agent that survives long projects | SQLite conversation history, semantic recall, graph memory, session digests, trajectory memory, and goal-aware compaction. | | Lower infrastructure cost | A default SQLite vector backend, local Ollama defaults, feature-gated bundles, and provider routing for simple vs. hard tasks. | | More than keyword memory | Typed graph facts, BFS recall, SYNAPSE spreading activation, MMR reranking, temporal decay, and write-quality gates. | -| Provider freedom | Ollama, Claude, OpenAI, Gemini, Candle, any OpenAI-compatible endpoint, and Gonka.ai via GonkaGate or the native signed-transport provider. | +| Provider freedom | Ollama, Claude, OpenAI, Gemini, Candle, any OpenAI-compatible endpoint, and distributed inference networks (Gonka, Cocoon TEE) for cost-sensitive or privacy-sensitive workloads. | | Agent-grade safety | Age-encrypted vault secrets, sandboxed tool execution, MCP injection detection, SSRF guards, PII filtering, and exfiltration checks. | | Daily operator ergonomics | CLI, TUI dashboard, MCP tools, plugins, skills, sub-agents, ACP for IDEs, A2A, scheduler, and JSON output modes. | @@ -63,36 +63,30 @@ zeph init zeph ``` -## Gonka.ai +## Distributed Inference -Zeph supports Gonka.ai inference in two modes: +Long-running agents are the worst-case workload for centralized API providers: thousands of calls per session, rate limits that pause mid-task, and costs that compound across every tool loop, memory retrieval, and sub-agent spawn. -**GonkaGate (OpenAI-compatible gateway):** store the `gp-...` key in the age vault as `ZEPH_COMPATIBLE_GONKAGATE_API_KEY` and use the `compatible` provider type: +Distributed inference networks change the economics. Compute is supplied by independent nodes rather than a single data center — which means no shared rate ceiling, no single vendor dependency, and in hardware-attested networks, provable isolation of your prompts from the node operator. -```toml -[[llm.providers]] -name = "gonkagate" -type = "compatible" -base_url = "https://api.gonkagate.com/v1" -model = "Qwen/Qwen3-235B-A22B-Instruct-2507-FP8" -default = true -``` +Zeph treats distributed networks as first-class providers alongside Ollama and cloud APIs, participating in the same adaptive routing — you can send cheap extraction and embedding work to a distributed node while reserving TEE-isolated compute for steps that touch sensitive context. + +| Network | Provider type | Characteristic | +|---|---|---| +| [Gonka](https://bug-ops.github.io/zeph/guides/gonka.html) | `gonka` / `compatible` | High-capacity distributed nodes, signed transport, OpenAI-compatible gateway | +| [Cocoon](https://bug-ops.github.io/zeph/guides/cocoon.html) | `cocoon` | Hardware TEE isolation — node operators cannot read prompts or weights | -**Native Gonka provider (signed transport):** use `type = "gonka"` with node endpoints. The native provider supports chat, streaming, embeddings, and tool calls over a signed request transport. Store the key as `ZEPH_GONKA_API_KEY` in the vault and declare nodes via `--init` wizard or directly in config: +Both plug into the standard provider declaration: ```toml [[llm.providers]] -name = "gonka" -type = "gonka" +name = "distributed" +type = "gonka" # or "cocoon", or "compatible" for gateway mode model = "qwen3-235b" default = true - -[[llm.gonka_nodes]] -url = "https://node.example.gonka.ai" -weight = 1 ``` -Run `zeph init` and select the GonkaGate option in the wizard to configure either mode interactively. +Run `zeph init` to configure either network interactively through the setup wizard. ## What Makes It Different From 002aa82e1a165aae39f809bafd51553de5721fef Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:23:30 +0200 Subject: [PATCH 3/6] docs(readme): add Telegram messenger-as-infrastructure section --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index f5e0c0405..b60ab17de 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,27 @@ default = true Run `zeph init` to configure either network interactively through the setup wizard. +## Messenger as Agent Infrastructure + +Most agents treat messaging apps as a thin input channel — user sends text, agent replies. Zeph's Telegram integration flips that model: the messenger becomes a coordination layer where agents serve public audiences, accept tasks from orchestrators, and talk to other bots. + +**Guest Mode** removes the assumption that every user is a registered Telegram account. A transparent local proxy intercepts guest queries from the Bot API and routes them to the agent without opening a second `getUpdates` connection (no 409 conflicts). The agent responds via `answerGuestQuery` — one call, no extra infra. This makes it practical to deploy public-facing agents that handle anonymous or unauthenticated requests. + +**Bot-to-Bot communication** lets Zeph register as a managed bot and accept tasks from other bots in a controlled chain. Consecutive bot replies are tracked per-chat, depth is capped at `max_bot_chain_depth`, and each inbound bot is validated against an allowlist — so the agent participates in multi-agent pipelines without becoming a relay for arbitrary bots. + +**Configurable streaming interval** (`stream_interval_ms`, default 3 s, minimum 500 ms) fixes a silent data-loss bug in the original hardcoded delay: responses that completed within a single interval window were discarded before Telegram saw them. Now the agent flushes on completion regardless of the timer. + +```toml +[telegram] +guest_mode = true +bot_to_bot = true +allowed_bots = ["orchestrator_bot", "scheduler_bot"] +max_bot_chain_depth = 3 +stream_interval_ms = 1500 +``` + +See the [Telegram guide](https://bug-ops.github.io/zeph/guides/telegram.html) for full configuration and Bot API 10.0 details. + ## What Makes It Different ### Memory is the product From cc8a644c58892657960bbe6934501d5b216769d9 Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:23:55 +0200 Subject: [PATCH 4/6] docs(readme): add Cocoon STT voice input via Telegram to messenger section --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b60ab17de..e014d1f19 100644 --- a/README.md +++ b/README.md @@ -96,15 +96,22 @@ Most agents treat messaging apps as a thin input channel — user sends text, ag **Bot-to-Bot communication** lets Zeph register as a managed bot and accept tasks from other bots in a controlled chain. Consecutive bot replies are tracked per-chat, depth is capped at `max_bot_chain_depth`, and each inbound bot is validated against an allowlist — so the agent participates in multi-agent pipelines without becoming a relay for arbitrary bots. +**Voice input via Cocoon STT.** The Telegram adapter detects voice and audio messages, downloads the file, and passes it to the configured speech-to-text provider. With `type = "cocoon"` and `stt_model` set, transcription runs inside a hardware TEE — audio bytes never leave the isolated enclave unencrypted. This makes voice-driven agentic workflows practical for sensitive use cases: a voice note becomes a task, without the audio touching a third-party transcription API. + **Configurable streaming interval** (`stream_interval_ms`, default 3 s, minimum 500 ms) fixes a silent data-loss bug in the original hardcoded delay: responses that completed within a single interval window were discarded before Telegram saw them. Now the agent flushes on completion regardless of the timer. ```toml [telegram] -guest_mode = true -bot_to_bot = true -allowed_bots = ["orchestrator_bot", "scheduler_bot"] +guest_mode = true +bot_to_bot = true +allowed_bots = ["orchestrator_bot", "scheduler_bot"] max_bot_chain_depth = 3 stream_interval_ms = 1500 + +[[llm.providers]] +name = "stt" +type = "cocoon" +stt_model = "whisper-large-v3" # transcribes Telegram voice messages inside TEE ``` See the [Telegram guide](https://bug-ops.github.io/zeph/guides/telegram.html) for full configuration and Bot API 10.0 details. From d9f8e205cdca2bb36752f012aacfe995093e5ef8 Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:27:02 +0200 Subject: [PATCH 5/6] docs(readme): add documentation links throughout all sections --- README.md | 64 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index e014d1f19..1cff3e173 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@ Unlike single-session assistants, Zeph is designed to remember *why* a decision | If you want... | Zeph gives you... | |---|---| -| An agent that survives long projects | SQLite conversation history, semantic recall, graph memory, session digests, trajectory memory, and goal-aware compaction. | -| Lower infrastructure cost | A default SQLite vector backend, local Ollama defaults, feature-gated bundles, and provider routing for simple vs. hard tasks. | -| More than keyword memory | Typed graph facts, BFS recall, SYNAPSE spreading activation, MMR reranking, temporal decay, and write-quality gates. | -| Provider freedom | Ollama, Claude, OpenAI, Gemini, Candle, any OpenAI-compatible endpoint, and distributed inference networks (Gonka, Cocoon TEE) for cost-sensitive or privacy-sensitive workloads. | -| Agent-grade safety | Age-encrypted vault secrets, sandboxed tool execution, MCP injection detection, SSRF guards, PII filtering, and exfiltration checks. | -| Daily operator ergonomics | CLI, TUI dashboard, MCP tools, plugins, skills, sub-agents, ACP for IDEs, A2A, scheduler, and JSON output modes. | +| An agent that survives long projects | SQLite conversation history, [semantic recall](https://bug-ops.github.io/zeph/guides/semantic-memory.html), [graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html), session digests, trajectory memory, and goal-aware compaction. | +| Lower infrastructure cost | A default SQLite vector backend, local [Ollama](https://ollama.ai) defaults, [feature-gated bundles](https://bug-ops.github.io/zeph/reference/feature-flags.html), and [provider routing](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html) for simple vs. hard tasks. | +| More than keyword memory | Typed graph facts, BFS recall, SYNAPSE spreading activation, MMR reranking, temporal decay, and write-quality gates. See [graph memory concepts](https://bug-ops.github.io/zeph/concepts/graph-memory.html). | +| Provider freedom | [Ollama](https://ollama.ai), Claude, OpenAI, Gemini, [Candle](https://bug-ops.github.io/zeph/advanced/candle.html), any OpenAI-compatible endpoint, and distributed inference networks ([Gonka](https://bug-ops.github.io/zeph/guides/gonka.html), [Cocoon TEE](https://bug-ops.github.io/zeph/guides/cocoon.html)) for cost-sensitive or privacy-sensitive workloads. | +| Agent-grade safety | [Age-encrypted](https://age-encryption.org) vault secrets, [sandboxed tool execution](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), [MCP injection detection](https://bug-ops.github.io/zeph/reference/security/mcp.html), SSRF guards, PII filtering, and exfiltration checks. | +| Daily operator ergonomics | CLI, [TUI](https://bug-ops.github.io/zeph/advanced/tui.html) dashboard, [MCP](https://bug-ops.github.io/zeph/guides/mcp.html) tools, plugins, [skills](https://bug-ops.github.io/zeph/concepts/skills.html), [sub-agents](https://bug-ops.github.io/zeph/advanced/sub-agents.html), [ACP](https://bug-ops.github.io/zeph/advanced/acp.html) for IDEs, [A2A](https://bug-ops.github.io/zeph/advanced/a2a.html), [scheduler](https://bug-ops.github.io/zeph/concepts/scheduler.html), and JSON output modes. | ## Quick Start @@ -54,7 +54,7 @@ zeph --tui > [!IMPORTANT] > Zeph requires Rust 1.95 or later when building from source. Pre-built binaries do not require a Rust toolchain. -For a local-first setup, run Ollama and pull the default lightweight models: +For a local-first setup, run [Ollama](https://ollama.ai) and pull the default lightweight models: ```bash ollama pull qwen3:8b @@ -69,7 +69,7 @@ Long-running agents are the worst-case workload for centralized API providers: t Distributed inference networks change the economics. Compute is supplied by independent nodes rather than a single data center — which means no shared rate ceiling, no single vendor dependency, and in hardware-attested networks, provable isolation of your prompts from the node operator. -Zeph treats distributed networks as first-class providers alongside Ollama and cloud APIs, participating in the same adaptive routing — you can send cheap extraction and embedding work to a distributed node while reserving TEE-isolated compute for steps that touch sensitive context. +Zeph treats distributed networks as first-class providers alongside [Ollama](https://ollama.ai) and cloud APIs, participating in the same [adaptive routing](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html) — you can send cheap extraction and embedding work to a distributed node while reserving TEE-isolated compute for steps that touch sensitive context. | Network | Provider type | Characteristic | |---|---|---| @@ -92,11 +92,11 @@ Run `zeph init` to configure either network interactively through the setup wiza Most agents treat messaging apps as a thin input channel — user sends text, agent replies. Zeph's Telegram integration flips that model: the messenger becomes a coordination layer where agents serve public audiences, accept tasks from orchestrators, and talk to other bots. -**Guest Mode** removes the assumption that every user is a registered Telegram account. A transparent local proxy intercepts guest queries from the Bot API and routes them to the agent without opening a second `getUpdates` connection (no 409 conflicts). The agent responds via `answerGuestQuery` — one call, no extra infra. This makes it practical to deploy public-facing agents that handle anonymous or unauthenticated requests. +**Guest Mode** removes the assumption that every user is a registered Telegram account. A transparent local proxy intercepts guest queries from the [Bot API 10.0](https://core.telegram.org/bots/api) and routes them to the agent without opening a second `getUpdates` connection (no 409 conflicts). The agent responds via [`answerGuestQuery`](https://core.telegram.org/bots/api#answerguestquery) — one call, no extra infra. This makes it practical to deploy public-facing agents that handle anonymous or unauthenticated requests. -**Bot-to-Bot communication** lets Zeph register as a managed bot and accept tasks from other bots in a controlled chain. Consecutive bot replies are tracked per-chat, depth is capped at `max_bot_chain_depth`, and each inbound bot is validated against an allowlist — so the agent participates in multi-agent pipelines without becoming a relay for arbitrary bots. +**Bot-to-Bot communication** lets Zeph register as a managed bot via [`setManagedBotAccessSettings`](https://core.telegram.org/bots/api#setmanagedbotaccesssettings) and accept tasks from other bots in a controlled chain. Consecutive bot replies are tracked per-chat, depth is capped at `max_bot_chain_depth`, and each inbound bot is validated against an allowlist — so the agent participates in multi-agent pipelines without becoming a relay for arbitrary bots. -**Voice input via Cocoon STT.** The Telegram adapter detects voice and audio messages, downloads the file, and passes it to the configured speech-to-text provider. With `type = "cocoon"` and `stt_model` set, transcription runs inside a hardware TEE — audio bytes never leave the isolated enclave unencrypted. This makes voice-driven agentic workflows practical for sensitive use cases: a voice note becomes a task, without the audio touching a third-party transcription API. +**Voice input via [Cocoon](https://bug-ops.github.io/zeph/guides/cocoon.html) STT.** The Telegram adapter detects voice and audio messages, downloads the file, and passes it to the configured speech-to-text provider. With `type = "cocoon"` and `stt_model` set, transcription runs inside a hardware TEE — audio bytes never leave the isolated enclave unencrypted. This makes voice-driven agentic workflows practical for sensitive use cases: a voice note becomes a task, without the audio touching a third-party transcription API. **Configurable streaming interval** (`stream_interval_ms`, default 3 s, minimum 500 ms) fixes a silent data-loss bug in the original hardcoded delay: responses that completed within a single interval window were discarded before Telegram saw them. Now the agent flushes on completion regardless of the timer. @@ -124,11 +124,11 @@ Zeph combines several memory layers instead of treating recall as a side feature | Layer | Purpose | |---|---| -| Working context | Keeps the current task coherent under context pressure. | -| Semantic memory | Stores conversations, tool outputs, documents, and summaries for retrieval. | -| Graph memory | Records entities, decisions, relationships, causality, temporal links, and hierarchy. | +| Working context | Keeps the current task coherent under context pressure. See [context budgets](https://bug-ops.github.io/zeph/concepts/context-budgets.html). | +| Semantic memory | Stores conversations, tool outputs, documents, and summaries for retrieval. See [semantic memory guide](https://bug-ops.github.io/zeph/guides/semantic-memory.html). | +| Graph memory | Records entities, decisions, relationships, causality, temporal links, and hierarchy. See [graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html). | | Episodic memory | Preserves session-level scenes, digests, goals, and trajectories. | -| Quality gates | Reject noisy writes, validate compaction, and log retrieval failures for later improvement. | +| Quality gates | Reject noisy writes, validate compaction, and log retrieval failures for later improvement. See [quality self-check](https://bug-ops.github.io/zeph/advanced/quality-self-check.html). | Ask "Why did we choose PostgreSQL?" and Zeph can traverse decision edges instead of searching raw chat text. @@ -136,15 +136,15 @@ Ask "Why did we choose PostgreSQL?" and Zeph can traverse decision edges instead Zeph does not require a heavyweight stack to be useful: -- The default vector backend is embedded SQLite. -- Qdrant is optional for larger semantic and graph workloads. -- The default local chat model is `qwen3.6:8b` through Ollama. -- Feature bundles let you build only what you need: `desktop`, `ide`, `server`, `chat`, `ml`, or `full`. +- The default vector backend is embedded [SQLite](https://www.sqlite.org). +- [Qdrant](https://qdrant.tech) is optional for larger semantic and graph workloads. +- The default local chat model is `qwen3:8b` through [Ollama](https://ollama.ai). +- [Feature bundles](https://bug-ops.github.io/zeph/reference/feature-flags.html) let you build only what you need: `desktop`, `ide`, `server`, `chat`, `ml`, or `full`. - Release builds are optimized for small native binaries. ### Multi-model by design -Declare providers once in `[[llm.providers]]`, then route work by complexity, cost, latency, and reliability: +Declare providers once in `[[llm.providers]]`, then [route work](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html) by complexity, cost, latency, and reliability: ```toml [[llm.providers]] @@ -168,7 +168,7 @@ Use local models for extraction, embeddings, routing, and summarization. Keep ex ### Tools without loose secrets -Secrets live in the Zeph age vault, not in `.env` files or shell profiles. Tool execution goes through trust gates, command filters, sandboxing, audit logs, and redaction paths. MCP tools are discovered and exposed without dropping the injection and authorization checks. +Secrets live in the Zeph [age](https://age-encryption.org) vault, not in `.env` files or shell profiles. Tool execution goes through trust gates, command filters, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), audit logs, and redaction paths. [MCP](https://bug-ops.github.io/zeph/guides/mcp.html) tools are discovered and exposed without dropping the [injection and authorization checks](https://bug-ops.github.io/zeph/reference/security/mcp.html). ## Demo @@ -224,17 +224,19 @@ cargo build --release --features full | Area | Highlights | |---|---| -| Memory | SQLite/PostgreSQL history, embedded SQLite vectors or Qdrant, [graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html), SYNAPSE, SleepGate, APEX-MEM write-quality gates, BeliefMem probabilistic edge layer, MemCoT Zoom-In/Out recall views, document RAG. | -| Context | Goal-aware compaction, TypedPage assembler pipeline, TACO output compression, tool-output archive, session recap, active-goal injection. | -| Skills | `SKILL.md` registry, hot reload, BM25 + embedding matching, trust levels, [self-learning skill improvement](https://bug-ops.github.io/zeph/guides/self-learning.html). | -| Providers | Ollama, Claude, OpenAI, Gemini, OpenAI-compatible APIs, [Gonka](https://bug-ops.github.io/zeph/guides/gonka.html) native inference, [Cocoon](https://bug-ops.github.io/zeph/guides/cocoon.html) decentralized TEE inference, Candle local inference, adaptive routing. | -| Tools | Shell, file, web, MCP, tool quotas, approval gates, audit trail, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), output compression, speculative dispatch, [ShadowSentinel](https://bug-ops.github.io/zeph/reference/security/shadow-sentinel.html) safety probes, TrajectorySentinel capability governance. | -| Interfaces | CLI, TUI, [Telegram](https://bug-ops.github.io/zeph/guides/telegram.html) (with Guest Mode and Bot-to-Bot), Discord, Slack, ACP, A2A, HTTP gateway, scheduler daemon. | -| Code intelligence | Tree-sitter indexing, semantic repo map, LSP diagnostics and hover context through MCP. | -| Observability | Debug dumps, JSONL mode, Prometheus metrics, OpenTelemetry traces, profiling builds. | +| Memory | SQLite/PostgreSQL history, embedded SQLite vectors or [Qdrant](https://qdrant.tech), [graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html), SYNAPSE, [SleepGate](https://bug-ops.github.io/zeph/advanced/sleep-gate.html), APEX-MEM write-quality gates, BeliefMem probabilistic edge layer, MemCoT Zoom-In/Out recall views, document RAG. | +| Context | [Goal-aware compaction](https://bug-ops.github.io/zeph/advanced/context.html), TypedPage assembler pipeline, TACO output compression, tool-output archive, session recap, active-goal injection. | +| Skills | `SKILL.md` registry, hot reload, BM25 + embedding matching, [trust levels](https://bug-ops.github.io/zeph/advanced/skill-trust.html), [self-learning skill improvement](https://bug-ops.github.io/zeph/guides/self-learning.html). | +| Providers | [Ollama](https://ollama.ai), Claude, OpenAI, Gemini, OpenAI-compatible APIs, [Gonka](https://bug-ops.github.io/zeph/guides/gonka.html) native inference, [Cocoon](https://bug-ops.github.io/zeph/guides/cocoon.html) decentralized TEE inference, [Candle](https://bug-ops.github.io/zeph/advanced/candle.html) local inference, [adaptive routing](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html). | +| Tools | Shell, file, web, [MCP](https://bug-ops.github.io/zeph/guides/mcp.html), tool quotas, approval gates, audit trail, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), output compression, speculative dispatch, [ShadowSentinel](https://bug-ops.github.io/zeph/reference/security/shadow-sentinel.html) safety probes, TrajectorySentinel capability governance. | +| Interfaces | CLI, [TUI](https://bug-ops.github.io/zeph/advanced/tui.html), [Telegram](https://bug-ops.github.io/zeph/guides/telegram.html) (with Guest Mode and Bot-to-Bot), Discord, Slack, [ACP](https://bug-ops.github.io/zeph/advanced/acp.html), [A2A](https://bug-ops.github.io/zeph/advanced/a2a.html), HTTP gateway, [scheduler daemon](https://bug-ops.github.io/zeph/concepts/scheduler.html). | +| Code intelligence | [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) indexing, semantic repo map, [LSP](https://bug-ops.github.io/zeph/guides/lsp.html) diagnostics and hover context through [MCP](https://bug-ops.github.io/zeph/guides/mcp.html). | +| Observability | [Debug dumps](https://bug-ops.github.io/zeph/advanced/debug-dump.html), JSONL mode, [Prometheus](https://bug-ops.github.io/zeph/guides/prometheus.html) metrics, [OpenTelemetry](https://opentelemetry.io) traces, profiling builds. | ## Architecture +See the [architecture overview](https://bug-ops.github.io/zeph/architecture/overview.html) and [crates reference](https://bug-ops.github.io/zeph/architecture/crates.html) for full details. + ```text zeph src/ CLI, bootstrap, init wizard, command handlers @@ -257,9 +259,13 @@ zeph - [Full documentation](https://bug-ops.github.io/zeph/) - [Installation guide](https://bug-ops.github.io/zeph/getting-started/installation.html) - [Configuration recipes](https://bug-ops.github.io/zeph/guides/config-recipes.html) +- [Memory concepts](https://bug-ops.github.io/zeph/concepts/memory.html) — graph, semantic, episodic layers - [Graph memory](https://bug-ops.github.io/zeph/concepts/graph-memory.html) +- [Adaptive inference routing](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html) +- [MCP integration](https://bug-ops.github.io/zeph/guides/mcp.html) - [Security model](https://bug-ops.github.io/zeph/reference/security.html) - [Feature flags](https://bug-ops.github.io/zeph/reference/feature-flags.html) +- [CLI reference](https://bug-ops.github.io/zeph/reference/cli.html) Zeph draws from published work on parallel tool execution, temporal knowledge graphs, agentic memory linking, failure-driven compression, retrieval quality, and multi-model routing. See [References & Inspirations](https://bug-ops.github.io/zeph/references.html) for the full list. From 9bbeae06fc460d280b3e8557aaaef4e13ba8d656 Mon Sep 17 00:00:00 2001 From: "Andrei G." Date: Mon, 11 May 2026 01:31:12 +0200 Subject: [PATCH 6/6] docs(readme): fix age-encryption.org redirect to github.com/FiloSottile/age --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1cff3e173..bfaeb16fc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Unlike single-session assistants, Zeph is designed to remember *why* a decision | Lower infrastructure cost | A default SQLite vector backend, local [Ollama](https://ollama.ai) defaults, [feature-gated bundles](https://bug-ops.github.io/zeph/reference/feature-flags.html), and [provider routing](https://bug-ops.github.io/zeph/advanced/adaptive-inference.html) for simple vs. hard tasks. | | More than keyword memory | Typed graph facts, BFS recall, SYNAPSE spreading activation, MMR reranking, temporal decay, and write-quality gates. See [graph memory concepts](https://bug-ops.github.io/zeph/concepts/graph-memory.html). | | Provider freedom | [Ollama](https://ollama.ai), Claude, OpenAI, Gemini, [Candle](https://bug-ops.github.io/zeph/advanced/candle.html), any OpenAI-compatible endpoint, and distributed inference networks ([Gonka](https://bug-ops.github.io/zeph/guides/gonka.html), [Cocoon TEE](https://bug-ops.github.io/zeph/guides/cocoon.html)) for cost-sensitive or privacy-sensitive workloads. | -| Agent-grade safety | [Age-encrypted](https://age-encryption.org) vault secrets, [sandboxed tool execution](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), [MCP injection detection](https://bug-ops.github.io/zeph/reference/security/mcp.html), SSRF guards, PII filtering, and exfiltration checks. | +| Agent-grade safety | [Age-encrypted](https://github.com/FiloSottile/age) vault secrets, [sandboxed tool execution](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), [MCP injection detection](https://bug-ops.github.io/zeph/reference/security/mcp.html), SSRF guards, PII filtering, and exfiltration checks. | | Daily operator ergonomics | CLI, [TUI](https://bug-ops.github.io/zeph/advanced/tui.html) dashboard, [MCP](https://bug-ops.github.io/zeph/guides/mcp.html) tools, plugins, [skills](https://bug-ops.github.io/zeph/concepts/skills.html), [sub-agents](https://bug-ops.github.io/zeph/advanced/sub-agents.html), [ACP](https://bug-ops.github.io/zeph/advanced/acp.html) for IDEs, [A2A](https://bug-ops.github.io/zeph/advanced/a2a.html), [scheduler](https://bug-ops.github.io/zeph/concepts/scheduler.html), and JSON output modes. | ## Quick Start @@ -168,7 +168,7 @@ Use local models for extraction, embeddings, routing, and summarization. Keep ex ### Tools without loose secrets -Secrets live in the Zeph [age](https://age-encryption.org) vault, not in `.env` files or shell profiles. Tool execution goes through trust gates, command filters, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), audit logs, and redaction paths. [MCP](https://bug-ops.github.io/zeph/guides/mcp.html) tools are discovered and exposed without dropping the [injection and authorization checks](https://bug-ops.github.io/zeph/reference/security/mcp.html). +Secrets live in the Zeph [age](https://github.com/FiloSottile/age) vault, not in `.env` files or shell profiles. Tool execution goes through trust gates, command filters, [sandboxing](https://bug-ops.github.io/zeph/reference/security/file-sandbox.html), audit logs, and redaction paths. [MCP](https://bug-ops.github.io/zeph/guides/mcp.html) tools are discovered and exposed without dropping the [injection and authorization checks](https://bug-ops.github.io/zeph/reference/security/mcp.html). ## Demo