agentmux 0.7.0

Multi-agent coordination runtime with inter-agent messaging across CLI, MCP, tmux, and ACP.
Documentation
use std::path::{Path, PathBuf};

use serde_json::json;
use uuid::Uuid;

use crate::configuration::{BundleConfiguration, TargetConfiguration};

use super::super::authorization::{
    AuthorizationContext, grant_authorized_ui_sessions, load_authorization_context,
    permission_max_pending,
};
use super::super::connection::BundleCatalog;
use super::super::delivery::{
    QuiescenceOptions, deliver_one_target, enqueue_sync_delivery, prompt_batch_settings,
};
use super::super::routing::{
    Addressing, Capability, OperationProfile, ResolvedRoute, requester_home_namespace,
    resolve_raww_route,
};
use super::super::{
    AsyncDeliveryTask, DeliveryPayloadMode, ListedSessionTransport, RelayError, RelayRequest,
    RelayResponse, SCHEMA_VERSION, SendOutcome, bare_session_id, canonical_session_id, relay_error,
    session_type_not_implemented,
};
use super::routed::{load_home_context, resolve_target_bundle, run_target_operation};
use super::sender::{SenderIdentity, resolve_sender_in_namespace};

/// The raww target's bundle, runtime, and the target bundle's authorization
/// (which gates delivery), resolved and existence-validated by `prepare_raww`
/// before authorization.
struct RawwPrepared {
    bundle: BundleConfiguration,
    runtime_directory: PathBuf,
    target_authorization: AuthorizationContext,
}

/// Entry point for the namespace-centric raww path. The requester is resolved and
/// authorized in its **home** namespace (`home_namespace`: its bound bundle, or
/// `GLOBAL`); the target's bundle is loaded separately for delivery, so a
/// cross-namespace raww authorizes the sender in its home rather than a borrowed
/// target bundle. See `dispatch_raww`.
pub(in crate::relay) fn handle_raww_routed(
    home_namespace: &str,
    home_runtime_directory: Option<&Path>,
    request: RelayRequest,
    configuration_root: &Path,
    bundle_catalog: &BundleCatalog,
) -> Result<RelayResponse, RelayError> {
    let RelayRequest::Raww {
        request_id,
        requester_session,
        target_session,
        text,
        no_enter,
    } = request
    else {
        return Err(relay_error(
            "internal_unexpected_request",
            "non-raww request routed to the raww dispatcher",
            None,
        ));
    };

    if target_session.trim().is_empty() {
        return Err(relay_error(
            "validation_invalid_params",
            "target_session must be non-empty",
            Some(json!({
                "field": "target_session",
            })),
        ));
    }
    if text.len() > 32 * 1024 {
        return Err(relay_error(
            "validation_invalid_params",
            "raww text exceeds maximum size of 32 KiB",
            Some(json!({
                "field": "text",
                "max_bytes": 32 * 1024,
                "bytes": text.len(),
            })),
        ));
    }

    // The requester is identified and authorized in its home namespace (operator
    // policy for `GLOBAL`, or the bundle's policy), never a borrowed target bundle.
    let (home_bundle, authorization) = load_home_context(home_namespace, configuration_root)?;
    let requester_session = bare_session_id(requester_session.as_str(), home_namespace);
    let sender = resolve_sender_in_namespace(
        home_bundle.as_ref(),
        &authorization,
        requester_session.as_str(),
        "requester_session",
    )?;

    // The spine owns resolution and authorization; `prepare_raww` validates
    // existence and loads the target bundle, `execute_raww` delivers the input.
    run_target_operation(
        home_namespace,
        &authorization,
        OperationProfile {
            capability: Capability::Raww,
            addressing: Addressing::SingleTarget,
        },
        || {
            resolve_raww_route(
                requester_home_namespace(sender.session_id.as_str(), home_namespace),
                sender.session_id.as_str(),
                target_session.as_str(),
            )
        },
        |route| {
            prepare_raww(
                route,
                home_namespace,
                home_bundle.as_ref(),
                home_runtime_directory,
                configuration_root,
                bundle_catalog,
            )
        },
        |route, prepared| {
            execute_raww(
                route,
                prepared,
                &sender,
                home_namespace,
                text,
                no_enter,
                request_id,
            )
        },
    )
}

/// Resolves the raww target's bundle, validates that the target is a configured
/// member, and loads the target bundle's authorization (which gates delivery).
/// Runs before authorization, so an unknown target sorts before
/// `authorization_forbidden`.
fn prepare_raww(
    route: &ResolvedRoute,
    home_namespace: &str,
    home_bundle: Option<&BundleConfiguration>,
    home_runtime_directory: Option<&Path>,
    configuration_root: &Path,
    bundle_catalog: &BundleCatalog,
) -> Result<RawwPrepared, RelayError> {
    let target_route = &route.targets[0];
    let target_bundle_name = target_route.bundle_name.as_str();
    let target_session_id = target_route
        .session_id
        .as_deref()
        .expect("raww target carries a session id");
    let (bundle, runtime_directory) = resolve_target_bundle(
        home_namespace,
        home_bundle,
        home_runtime_directory,
        target_bundle_name,
        configuration_root,
        bundle_catalog,
    )?;
    if !bundle
        .members
        .iter()
        .any(|member| member.id == target_session_id)
    {
        return Err(relay_error(
            "validation_unknown_target",
            "target_session is not a canonical configured target identifier",
            Some(json!({
                "target_session": canonical_session_id(target_session_id, target_bundle_name),
            })),
        ));
    }
    let target_authorization = load_authorization_context(configuration_root, Some(&bundle))?;
    Ok(RawwPrepared {
        bundle,
        runtime_directory,
        target_authorization,
    })
}

/// Delivers the raw input to the authorized target and builds the response. The
/// target is guaranteed present by `prepare_raww`. Permission deciders and the
/// queue bound come from the target bundle's authorization, where delivery is
/// gated.
fn execute_raww(
    route: &ResolvedRoute,
    prepared: RawwPrepared,
    sender: &SenderIdentity,
    home_namespace: &str,
    text: String,
    no_enter: bool,
    request_id: Option<String>,
) -> Result<RelayResponse, RelayError> {
    let RawwPrepared {
        bundle: raww_bundle,
        runtime_directory: raww_runtime_directory,
        target_authorization,
    } = prepared;
    let target_session_id = route.targets[0]
        .session_id
        .as_deref()
        .expect("raww target carries a session id");
    let target_member = raww_bundle
        .members
        .iter()
        .find(|member| member.id == target_session_id)
        .expect("raww target existence validated in prepare_raww");

    let transport = match &target_member.target {
        TargetConfiguration::Tmux(_) => ListedSessionTransport::Tmux,
        TargetConfiguration::Acp(_) => ListedSessionTransport::Acp,
        TargetConfiguration::Ui | TargetConfiguration::Pubsub => {
            return Err(session_type_not_implemented(
                target_member.id.as_str(),
                target_member.target.session_type(),
            ));
        }
    };
    let message_id = Uuid::new_v4().to_string();
    let sender_member = sender.to_bundle_member();
    let permission_decider_sessions =
        grant_authorized_ui_sessions(&target_authorization, &raww_bundle);
    let queue_max_pending = permission_max_pending(&target_authorization);
    let task = AsyncDeliveryTask {
        bundle: raww_bundle.clone(),
        sender_bundle_name: home_namespace.to_string(),
        sender: sender_member,
        // Raw input does not carry verified sender attribution, and its targets
        // are never UI streams.
        authenticated_identity: None,
        all_target_sessions: vec![target_member.id.clone()],
        target_session: target_member.id.clone(),
        target_is_ui: false,
        message: text,
        message_id: message_id.clone(),
        quiescence: QuiescenceOptions::for_sync(None, None, None),
        batch_settings: prompt_batch_settings(),
        runtime_directory: raww_runtime_directory,
        completion_sender: None,
        payload_mode: DeliveryPayloadMode::RawInput,
        append_enter: !no_enter,
        permission_decider_sessions,
        permission_max_pending: queue_max_pending,
    };

    let result = match &target_member.target {
        TargetConfiguration::Acp(_) => enqueue_sync_delivery(task)?,
        TargetConfiguration::Tmux(_) => deliver_one_target(&task)?,
        TargetConfiguration::Ui | TargetConfiguration::Pubsub => {
            return Err(session_type_not_implemented(
                target_member.id.as_str(),
                target_member.target.session_type(),
            ));
        }
    };
    if result.outcome != SendOutcome::Delivered {
        let reason = result
            .reason
            .unwrap_or_else(|| "raww dispatch failed".to_string());
        let code = if matches!(
            result.reason_code.as_deref(),
            Some("runtime_acp_worker_unavailable")
        ) {
            "runtime_target_unavailable"
        } else {
            "runtime_transport_write_failed"
        };
        return Err(relay_error(
            code,
            "raww dispatch failed",
            Some(json!({
                "target_session": result.target_session,
                "transport": transport,
                "reason": reason,
                "reason_code": result.reason_code,
            })),
        ));
    }

    let details = if transport == ListedSessionTransport::Acp {
        Some(json!({
            "delivery_phase": "accepted_in_progress",
        }))
    } else {
        Some(json!({
            "delivery_phase": "accepted_dispatched",
        }))
    };
    Ok(RelayResponse::Raww {
        schema_version: SCHEMA_VERSION.to_string(),
        status: "accepted".to_string(),
        target_session: canonical_session_id(
            target_member.id.as_str(),
            raww_bundle.bundle_name.as_str(),
        ),
        transport,
        request_id,
        message_id: Some(message_id),
        details,
    })
}