Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]
### Removed

- `zeph-agent-tools`: removed the unused `AgentChannel` sealed trait and its supporting
`ChannelSinkError`/`ToolEventStart`/`ToolEventOutput`/`Sealed` types (`channel.rs`,
`error.rs`, `sealed.rs`), along with `ToolDispatchError` (`error.rs`) — dead scaffolding
from an abandoned dispatcher-extraction plan (issue #3516, closed) with zero implementors
or consumers anywhere in the workspace (#6480). The crate now exposes only `doom_loop_hash`,
its sole real production consumer (`zeph-core`'s tool tier loop). Dropped the now-unused
`futures`, `serde`, `serde_json`, `thiserror`, `tokio`, `tracing`, `zeph-common`, `zeph-llm`,
and `zeph-tools` dependencies along with the `sqlite`/`postgres` feature forwarding they
existed to support — `zeph-agent-tools` now has zero workspace or external dependencies.
Behavior of `doom_loop_hash` and its call site are unchanged.

### Changed

- `zeph-skills`: `embed_skills_with_timeout` now tries `LlmProvider::embed_batch` first
Expand Down
11 changes: 0 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ zeph-acp = { path = "crates/zeph-acp", default-features = false, version = "0.22
zeph-agent-context = { path = "crates/zeph-agent-context", default-features = false, version = "0.22.2" }
zeph-agent-feedback = { path = "crates/zeph-agent-feedback", version = "0.22.2" }
zeph-agent-persistence = { path = "crates/zeph-agent-persistence", default-features = false, version = "0.22.2" }
zeph-agent-tools = { path = "crates/zeph-agent-tools", default-features = false, version = "0.22.2" }
zeph-agent-tools = { path = "crates/zeph-agent-tools", version = "0.22.2" }
zeph-bench = { path = "crates/zeph-bench", default-features = false, version = "0.22.2" }
zeph-channels = { path = "crates/zeph-channels", default-features = false, version = "0.22.2" }
zeph-commands = { path = "crates/zeph-commands", version = "0.22.2" }
Expand Down
2 changes: 1 addition & 1 deletion crates/zeph-agent-context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//! This crate provides [`service::ContextService`] — a stateless façade for all
//! context-assembly operations that were previously implemented directly on `Agent<C>`
//! in `zeph-core`. Extracting this logic means that editing context-assembly code does
//! not trigger recompilation of the tool dispatcher (`zeph-agent-tools`) or the
//! not trigger recompilation of the doom-loop detector (`zeph-agent-tools`) or the
//! persistence layer (`zeph-agent-persistence`).
//!
//! # Architecture
Expand Down
9 changes: 3 additions & 6 deletions crates/zeph-agent-tools/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# zeph-agent-tools Guide

Tool-dispatch primitives consumed by the tool loop in `zeph-core`: the sealed `AgentChannel` trait, borrowed event carriers (`ToolEventStart`, `ToolEventOutput`), and doom-loop detection (`doom_loop_hash`).
Doom-loop detection (`doom_loop_hash`) consumed by the tool loop in `zeph-core`.

- Start with crate-local checks: `cargo build -p zeph-agent-tools`, `cargo nextest run -p zeph-agent-tools`, `cargo clippy -p zeph-agent-tools --all-targets -- -D warnings`.
- Read `specs/006-tools/spec.md` before changing the dispatch contract or tool-result handling.
- Architecture invariant: this crate MUST NOT depend on `zeph-core` or `zeph-channels`. `AgentChannel` is a minimal, sealed trait specifically to avoid the circular dependency that `zeph-core::channel::Channel` would create — never break this by adding those deps.
- `AgentChannel` is sealed via the `Sealed` trait: external implementations are forbidden by design. `zeph-core` implements it through its local `AgentChannelView<'a, C>` adapter.
- Crate status: Phase-2 scaffolding (issue #3516, closed). The `AgentChannel` trait and borrowed event carriers are complete, but no `zeph-core` adapter implements them and no `ToolDispatcher` extraction has landed or is in flight — that plan was abandoned, not deferred; re-opening it requires a new tracking issue. Per #6222/#6084, the crate now declares only the 3 `zeph-*` deps it actually uses (`zeph-common`, `zeph-llm`, `zeph-tools`) — do not re-add `zeph-agent-persistence`/`zeph-config`/`zeph-context`/`zeph-mcp`/`zeph-orchestration`/`zeph-sanitizer`/`zeph-skills` speculatively; add a dependency only alongside the code that actually needs it.
- Architecture invariant: this crate MUST NOT depend on `zeph-core` or `zeph-channels`.
- Crate status: previously carried a sealed `AgentChannel` dispatcher-extraction trait (issue #3516, closed) with zero implementors anywhere in the workspace; removed as dead code (issue #6480). That dispatcher-extraction plan is abandoned, not deferred — reviving it requires a new tracking issue. Add a dependency only alongside the code that actually needs it.
- Doom-loop detection is agent-safety critical: any change to `doom_loop_hash` or its hashing inputs needs regression coverage so repeated tool calls are still detected.
- LLM serialization gate: once tool dispatch / batch tool-result processing is extracted here, changes to those paths require a live session test with a real tool call before merge.
21 changes: 1 addition & 20 deletions crates/zeph-agent-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,8 @@ homepage.workspace = true
keywords.workspace = true
categories.workspace = true
publish.workspace = true
description = "Agent tool dispatcher for Zeph: native tool loop, retry, confirmation, batch tool-result processing."
description = "Doom-loop detection utilities for the Zeph agent tool dispatch loop."
readme = "README.md"

[dependencies]
futures.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
thiserror.workspace = true
tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] }
tracing.workspace = true
zeph-common.workspace = true
zeph-llm.workspace = true
zeph-tools.workspace = true

[features]
# `zeph-tools` (and transitively `zeph-db`) requires a backend to compile;
# default to `sqlite` so this crate builds in isolation, and expose `postgres` for
# PostgreSQL deployments (#4956).
default = ["sqlite"]
sqlite = ["zeph-tools/sqlite"]
postgres = ["zeph-tools/postgres"]

[lints]
workspace = true
47 changes: 6 additions & 41 deletions crates/zeph-agent-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](../../LICENSE)
[![MSRV](https://img.shields.io/badge/MSRV-1.97-blue)](https://www.rust-lang.org)

Agent tool dispatcher for Zeph: provides the `AgentChannel` sealed trait, borrowed event
carriers, and doom-loop detection utilities used by the tool dispatch loop in `zeph-core`.
Doom-loop detection utilities for the Zeph tool dispatch loop.

## Key types

| Type / Function | Description |
|-----------------|-------------|
| `AgentChannel` | Sealed async sink trait the tool dispatcher uses to emit events to the user surface |
| `ToolEventStart<'a>` | Borrowed payload for a tool-start event (zero-copy through the seam) |
| `ToolEventOutput<'a>` | Borrowed payload for a tool-output event, including body and error flag |
| `ChannelSinkError` | Concrete error returned by every `AgentChannel` method |
| `ToolDispatchError` | Error enum covering LLM, tool, MCP, timeout, and channel failures |
| `doom_loop_hash` | Hash message content with volatile tool IDs normalized out |
| `Sealed` | Marker trait that prevents external `AgentChannel` implementations |

## Usage

### Doom-loop detection

```rust
use zeph_agent_tools::doom_loop_hash;

Expand All @@ -34,40 +25,14 @@ let h2 = doom_loop_hash("[tool_result: xyz789] same output");
assert_eq!(h1, h2);
```

### Implementing `AgentChannel` (zeph-core only)

```rust,no_run
// The trait is sealed — only zeph-core can implement it.
// zeph-core provides: impl<C: Channel> AgentChannel for AgentChannelView<'_, C>
//
// Dispatcher usage (generic, no Box/dyn):
async fn dispatch<Ch: zeph_agent_tools::AgentChannel>(ch: &mut Ch, text: &str) {
ch.send(text).await.ok();
}
```

## Architecture

`zeph-agent-tools` does **not** depend on `zeph-core` or `zeph-channels`. It defines its own
minimal `AgentChannel` trait (sealed via `Sealed`) which `zeph-core` implements through a local
adapter type `AgentChannelView<'a, C>`. This avoids the circular dependency that would arise
from referencing `zeph_core::channel::Channel` directly from inside the dispatcher crate.

`zeph-core` depends on this crate; downstream channels (`zeph-channels`) do not.

## Features

| Feature | Default | Description |
|---------|---------|-------------|
| `sqlite` | on | SQLite backend, forwarded to `zeph-tools/sqlite` |
| `postgres` | off | PostgreSQL backend, forwarded to `zeph-tools/postgres` |

A storage backend must be selected for the crate to compile; `sqlite` is the default.
`zeph-agent-tools` has no dependencies on other workspace crates. `zeph-core` calls
`doom_loop_hash` from the tool dispatch loop to detect repeated tool-call cycles.

> **Note:** This crate is Phase 2 scaffolding from issue #3516 (closed). The `AgentChannel`
> trait and borrowed event carriers are complete, but no `zeph-core` adapter currently
> implements them and no `ToolDispatcher` extraction has landed. Re-opening this work would
> require a new tracking issue.
> **Note:** This crate previously carried a sealed `AgentChannel` dispatcher-extraction trait
> (issue #3516) with no implementors anywhere in the workspace; it was removed as dead code
> (issue #6480). Reviving that dispatcher-extraction plan needs a fresh tracking issue.

## License

Expand Down
Loading
Loading