770d5bf459
Web Push: the VAPID keypair, subscription store, `/api/push/*`, the service-worker push handlers, the presence heartbeat that only existed to suppress pushes, the Notifications settings tab, and the `[web]` config section. Drops p256, hkdf, aes-gcm, jsonwebtoken and getrandom. Session triage: per-session color, web pin, and archive are gone from the Instance, the REST API, the CLI (`session color` / `archive` / `unarchive`), the TUI (the `z` and `U` keybinds, the Archived sidebar section, group archive-all) and the web sidebar (row badges, context menu, bulk actions, sort tiers, optimistic overlay). Unread stays: the marker, the auto-mark on a finished turn, dwell-to-read and the mark-read-on-open endpoint are all unchanged; only the manual toggle is removed. Claude Code session import: the on-disk scanner, `aoe session import`, `/api/claude-sessions`, and the wizard's import tab. Repo clone: `/api/git/clone`, `clone_repo` / `clone_bare_repo`, the wizard's Clone URL tab and the dashboard action. Markdown: ToolCards now renders through react-markdown like MarkdownFileView instead of carrying a second stack, dropping marked and dompurify. Dead dependencies with no call sites: portable-pty, serde_yaml, glob, clsx. Web multi-select is left in place but no longer drives anything; it existed only for bulk pin/archive. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
274 lines
10 KiB
TOML
274 lines
10 KiB
TOML
[workspace]
|
|
members = [".", "xtask", "aoe-settings-derive"]
|
|
|
|
[package]
|
|
name = "agent-of-empires"
|
|
version = "1.15.0"
|
|
edition = "2021"
|
|
rust-version = "1.85"
|
|
authors = ["Agent of Empires Contributors"]
|
|
description = "Terminal session manager for AI coding agents"
|
|
license = "MIT"
|
|
repository = "https://github.com/agent-of-empires/agent-of-empires"
|
|
keywords = ["tmux", "tui", "ai", "claude", "terminal"]
|
|
categories = ["command-line-utilities", "development-tools"]
|
|
|
|
[dependencies]
|
|
# CLI
|
|
clap = { version = "4.6", features = ["derive", "env", "string"] }
|
|
clap_complete = "4.6"
|
|
|
|
# TUI
|
|
ratatui = { version = "0.30", features = ["crossterm"] }
|
|
crossterm = { version = "0.29", features = ["event-stream"] }
|
|
ansi-to-tui = "8.0"
|
|
# In-process VT emulator for the default live-preview path (`src/tmux/vt.rs`,
|
|
# opt out with `AOE_VT_LIVE=0`): parse a pane's raw byte stream into an owned
|
|
# grid instead of scraping `capture-pane` snapshots.
|
|
vt100 = "0.16"
|
|
ratatui-textarea = "0.9"
|
|
tui-input = "0.15"
|
|
# Markdown parsing for the structured view transcript. We map events to ratatui
|
|
# Lines ourselves (see src/tui/structured_view/render.rs) so raw markers are
|
|
# stripped and styling tracks the app theme; default-features = false
|
|
# drops the unused HTML renderer.
|
|
pulldown-cmark = { version = "0.13", default-features = false }
|
|
|
|
# Async runtime
|
|
tokio = { version = "1.52", features = ["full"] }
|
|
|
|
# Settings single-source-of-truth derive (#1692)
|
|
aoe-settings-derive = { path = "aoe-settings-derive" }
|
|
|
|
# Serialization
|
|
serde = { version = "1.0", features = ["derive"] }
|
|
serde_ignored = "0.1"
|
|
serde_json = "1.0"
|
|
toml = "1.1"
|
|
toml_edit = "0.25"
|
|
|
|
# File watching
|
|
notify = "8.2"
|
|
|
|
# Fuzzy matching
|
|
nucleo-matcher = "0.3"
|
|
|
|
# Shell-style splitting of custom-agent ACP command strings into argv
|
|
shell-words = "1.1"
|
|
|
|
# Insertion-ordered id → Instance map for HomeView.instances.
|
|
indexmap = "2"
|
|
|
|
# Error handling
|
|
thiserror = "2.0"
|
|
anyhow = "1.0"
|
|
|
|
# Time handling
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
|
|
# UUID generation
|
|
uuid = { version = "1.23", features = ["v4"] }
|
|
|
|
# Random
|
|
rand = "0.10"
|
|
|
|
# Directory utilities
|
|
dirs = "6.0"
|
|
|
|
# Logging
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
|
|
# HTTP client (for updates)
|
|
reqwest = { version = "0.13", features = ["json", "rustls", "stream"], default-features = false }
|
|
|
|
# Percent-encode path segments (release tags) for GitHub API URLs.
|
|
percent-encoding = "2"
|
|
|
|
# Unix sockets + futures-compat for ACP byte streams
|
|
tokio-util = { version = "0.7", features = ["codec", "compat"] }
|
|
|
|
# Process handling
|
|
nix = { version = "0.31", features = ["signal", "process", "net", "fs", "resource", "dir", "user", "poll"] }
|
|
|
|
# Unicode width + normalization (NFKD used to fold accents in title-derived branch names)
|
|
unicode-normalization = "0.1"
|
|
unicode-segmentation = "1"
|
|
unicode-width = "0.2"
|
|
|
|
# Terminal spinners
|
|
rattles = "0.3"
|
|
|
|
# Regex
|
|
regex = "1.10"
|
|
|
|
# Git operations. git2's `default` is empty, so this drops `https`/`ssh` and
|
|
# with them openssl-sys, which built OpenSSL from C source on every cold cache.
|
|
# Safe because nothing reaches a remote through libgit2: src/git/remote.rs only
|
|
# reads origin's configured URL, and `Repository::clone` appears only in tests
|
|
# cloning a tempdir over libgit2's built-in local transport.
|
|
git2 = "0.21"
|
|
|
|
# Diff computation
|
|
similar = "3.1"
|
|
|
|
# Hashing
|
|
sha2 = "0.11"
|
|
|
|
# File locking
|
|
fs2 = "0.4"
|
|
|
|
# Stream utilities (for crossterm EventStream)
|
|
futures-util = "0.3"
|
|
|
|
# Temporary files and directories
|
|
tempfile = "3.14"
|
|
|
|
# PATH lookup for external viewers (lnav, bat, less) used by `aoe logs`.
|
|
which = "8.0"
|
|
|
|
# Local SQLite reader for opencode's session store. Bundled to avoid a
|
|
# system libsqlite3 dependency. Used to read session state without spawning
|
|
# `opencode session list`, which leaks a 4.5MB /tmp/.<hash>.so per invocation
|
|
# via opencode's bun:ffi OpenTUI extract path (see anomalyco/opencode#6523).
|
|
rusqlite = { version = "0.40", features = ["bundled"] }
|
|
|
|
# Web server (optional, behind "serve" feature)
|
|
axum = { version = "0.8", features = ["ws"], optional = true }
|
|
# Cross-platform browser launcher for `aoe serve --open`.
|
|
webbrowser = { version = "1", optional = true }
|
|
tower-http = { version = "0.7", features = ["fs"], optional = true }
|
|
rust-embed = { version = "8", features = ["debug-embed"], optional = true }
|
|
mime_guess = { version = "2.0", optional = true }
|
|
|
|
# Used by the TUI for OSC 52 clipboard writes (preview drag-select in
|
|
# live mode).
|
|
base64 = "0.23"
|
|
|
|
# Agent Client Protocol — drives the structured view surface bundled with `serve`.
|
|
agent-client-protocol = { version = "1.0", optional = true, features = ["unstable_end_turn_token_usage", "unstable_elicitation", "unstable_session_fork"] }
|
|
|
|
# Semver parsing for ACP adapter compatibility checks (see src/acp/agent_compat.rs).
|
|
semver = { version = "1", optional = true }
|
|
|
|
# Raw-deflate codec behind the live-WS frame stream (src/server/live_ws.rs).
|
|
flate2 = "1"
|
|
|
|
# WebSocket client for the structured view-in-TUI view: subscribes to the daemon's
|
|
# `/sessions/{id}/acp/ws` stream and pumps frames into the local reducer.
|
|
# Folded into the `serve` feature alongside the rest of the structured view surface;
|
|
# the daemon itself uses axum's built-in WS support and never pulls this in.
|
|
tokio-tungstenite = { version = "0.30", default-features = false, features = ["rustls-tls-webpki-roots", "connect"], optional = true }
|
|
|
|
# Capability-safe file opens for the session file-read endpoint (#3088): open
|
|
# beneath a Dir so a component swapped after the containment check cannot
|
|
# escape the intended root.
|
|
cap-std = { version = "4.0.2", optional = true }
|
|
|
|
# Unix-only: O_NOFOLLOW and friends for race-free directory walks (no std constants).
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
[features]
|
|
# Lean by default: a plain `cargo build` needs no Node/npm. `serve` (the web
|
|
# dashboard) stays opt-in (`cargo build --features serve`). Released binaries
|
|
# are built `--features serve`, so every distributed binary ships the dashboard.
|
|
default = []
|
|
# Re-exports private tmux env helpers via `crate::tmux::test_support` so that
|
|
# integration tests in `tests/` can poke them. Not enabled by default — only
|
|
# used by `cargo test`.
|
|
test-support = []
|
|
# Gates the `e2e` test target (tests/e2e/main.rs). Off by default so CI can run
|
|
# the serve suite as two parallel shards without enumerating every non-e2e test
|
|
# binary: `cargo test --features serve` runs everything except e2e (the target
|
|
# is skipped when the feature is off), and `cargo test --features serve,e2e-tests
|
|
# --test e2e` runs e2e only. Run the full serve suite locally with
|
|
# `cargo test --features serve,e2e-tests`. Naming the target explicitly
|
|
# (`cargo test --test e2e`) without the feature errors loudly rather than
|
|
# skipping silently.
|
|
e2e-tests = []
|
|
serve = [
|
|
"axum",
|
|
"tower-http",
|
|
"rust-embed",
|
|
"mime_guess",
|
|
"webbrowser",
|
|
# Structured view (ACP-based structured rendering of agent state) ships
|
|
# alongside the web dashboard — the two share state, REST routes,
|
|
# and the WebSocket fanout. Folded into `serve` so building the
|
|
# dashboard always includes the structured view surface; pulling them
|
|
# apart later is straightforward (structured view code lives entirely
|
|
# under src/acp/).
|
|
"agent-client-protocol",
|
|
"semver",
|
|
"tokio-tungstenite",
|
|
# Sandboxed, race-safe file reads for the session file endpoint (#3088):
|
|
# open beneath a capability Dir so a symlink or component swapped between
|
|
# the confinement check and the open cannot escape the intended root.
|
|
"cap-std",
|
|
]
|
|
cap-std = ["dep:cap-std"]
|
|
|
|
[dev-dependencies]
|
|
serial_test = "3.4"
|
|
# Test-only tracing capture (#2756, I4): asserts the equal-timestamp guard's
|
|
# drop branch logged. Its target `session.store` is rejected by the default
|
|
# `agent_of_empires=trace` env filter, so `no-env-filter` is required; the
|
|
# test scopes to its own span and matches the message, so wide capture is safe.
|
|
tracing-test = { version = "0.2", features = ["no-env-filter"] }
|
|
# Integration tests are separate crates and don't inherit the normal
|
|
# `serde_json` dependency; the acp-runner orphan test parses a worker
|
|
# registry record to mutate its pid structurally.
|
|
serde_json = "1.0"
|
|
# Integration tests are separate crates and don't inherit the normal `toml`
|
|
# dependency; the build-cache guard test parses .cargo/config.toml.
|
|
toml = "1.1"
|
|
cargo-husky = { version = "1", default-features = false, features = ["precommit-hook", "run-cargo-fmt"] }
|
|
# Test-only axum dep, used by the update e2e fixture server that serves
|
|
# a fake release tarball. The runtime code uses reqwest, not axum.
|
|
axum = { version = "0.8", features = ["ws"] }
|
|
# Test-only tower dep for `ServiceExt::oneshot`, so the DNS-rebinding gate
|
|
# (#2735) can be driven through the real router without binding a socket.
|
|
tower = { version = "0.5", features = ["util"] }
|
|
# Self-dev-dependency: enables the `test-support` feature when building
|
|
# integration tests so they can reach `crate::tmux::test_support`. This is
|
|
# the standard Cargo pattern for opt-in test-only re-exports; the lib build
|
|
# (and release binaries) never see the feature. `default-features = false`
|
|
# matters: without it this entry re-enables the default `serve` feature
|
|
# under `cargo test --no-default-features`, making that CI job meaningless.
|
|
agent-of-empires = { path = ".", default-features = false, features = ["test-support"] }
|
|
|
|
[profile.release]
|
|
lto = true
|
|
codegen-units = 1
|
|
strip = true
|
|
|
|
[profile.dev-release]
|
|
inherits = "release"
|
|
lto = false
|
|
codegen-units = 16
|
|
# Land on the release namespace (app dir, tmux prefix, serve port) so a
|
|
# fast-compiled dev-release binary shares state with installed release
|
|
# builds. Use the default `dev` profile when you want the isolated
|
|
# `-dev` namespace.
|
|
debug-assertions = false
|
|
|
|
[[test]]
|
|
# ACP runner is part of the serve / structured-view surface.
|
|
name = "acp_runner_orphan"
|
|
path = "tests/acp_runner_orphan.rs"
|
|
required-features = ["serve"]
|
|
|
|
[[test]]
|
|
# Explicit target so the `e2e-tests` feature gate applies. Without this entry
|
|
# Cargo auto-discovers tests/e2e/main.rs unconditionally; the gate lets CI split
|
|
# the serve suite into "everything except e2e" and "e2e only" shards. The other
|
|
# standalone test binaries stay auto-discovered.
|
|
name = "e2e"
|
|
path = "tests/e2e/main.rs"
|
|
required-features = ["e2e-tests"]
|
|
|
|
[[bin]]
|
|
name = "aoe"
|
|
path = "src/main.rs"
|