Skip to main content

Crate car_server_core

Crate car_server_core 

Source
Expand description

Transport-neutral library extracted from car-server.

Holds the JSON-RPC dispatcher, per-client session state, and the WebSocket channel plumbing. The standalone car-server binary is a thin wrapper that loads ~/.car/env, initializes telemetry, spawns the dream loop, binds a TCP listener, and on each connection calls run_dispatch.

Embedders (e.g. the future tokhn-daemon at U7) construct a ServerState via ServerState::embedded (or ServerStateConfig for advanced wiring), accept WebSocket connections in their own listener, and call run_dispatch directly — without re-implementing the dispatcher.

§Library boundary contract

Per the U1 plan, this library MUST NOT:

  • spawn the dream loop (caller decides),
  • initialize telemetry (caller decides),
  • load ~/.car/env (caller decides).

Those bootstraps stay in the embedder’s main. This contract prevents the dual-memgine bug U7 mitigates: if the library silently spawned its own dream loop, embedded users would end up with two memgine engines (the embedder’s plus the library’s).

§Lock primitive

ClientSession.memgine uses Arc<tokio::sync::Mutex<MemgineEngine>> per the “one-wrapper rule” — dispatcher handlers can hold the lock across .await points without risking poisoning, and tokio’s Mutex does not poison so a panicking handler does not poison the engine for sibling connections.

Re-exports§

pub use admission::InferenceAdmission;
pub use admission::ENV_MAX_CONCURRENT;
pub use coder::heal_service::spawn_heal_cadence;
pub use coder::watchdog::spawn_coder_session_watchdog;
pub use command_scheduler::spawn_command_scheduler;
pub use evolution::seed_evolution_interval;
pub use evolution::spawn_evolution_cadence;
pub use feedback_drain::spawn_feedback_drain;
pub use feedback_drain::wake_feedback_drain;
pub use handler::handle_connection;
pub use handler::reap_orphaned_sandboxes_at_boot;
pub use handler::reconcile_os_schedules_at_boot;
pub use handler::recover_workflow_checkpoints;
pub use handler::run_concierge_check;
pub use handler::run_dispatch;
pub use handler::run_idle_backend_eviction;
pub use handler::run_upgrade_nudge_check;
pub use handler::seed_memgine_config;
pub use handler::JsonRpcError;
pub use handler::JsonRpcMessage;
pub use handler::JsonRpcResponse;
pub use registry_reaper::spawn_stale_registry_reaper;
pub use self_update::run_update as run_self_update;
pub use self_update::spawn_auto_update;
pub use self_update::UpdateOptions;
pub use selfheal::spawn_selfheal_cadence;
pub use selfheal::SelfhealEvidence;
pub use selfheal::SelfhealReplayVerbProbe;
pub use selfheal::SelfhealRoute;
pub use selfheal::SelfhealSourceProbe;
pub use selfheal::DEFAULT_SELFHEAL_INTERVAL_SECS;
pub use selfheal::SELFHEAL_INTERVAL_ENV;
pub use handler::handle_connection_unix;
pub use inference_worker::run_mlx_worker;
pub use inference_worker::WorkerOffload;
pub use run_store::RetentionConfig;
pub use run_store::RunStatus;
pub use run_store::RunStore;
pub use run_store::RunSummary;
pub use run_store::DEFAULT_MAX_AGE_DAYS;
pub use run_store::DEFAULT_MAX_RUNS_PER_AGENT;
pub use run_trace::record_turns;
pub use session::ApprovalGate;
pub use session::ClientSession;
pub use session::RecordRunTurnsOutcome;
pub use session::RunMeta;
pub use session::ServerState;
pub use session::ServerStateConfig;
pub use session::WsChannel;
pub use session::WsMemgineIngestSink;
pub use session::WsSink;
pub use session::WsToolExecutor;
pub use session::WsVoiceEventSink;
pub use session::RECORD_TURNS_RUN_CEILING;
pub use session::RUN_COMPLETE_GRACE;

Modules§

a2a
FFI wrappers for the car-a2a server lifecycle.
admission
Process-wide admission control for inference RPC handlers.
agent_permissions
Durable store + wire surface for the per-agent approval policy (car_policy::AgentPermissionPolicy).
approval_core
Channel-agnostic approval semantics (Unit 1 — the lifted core).
assistant
Parslee Core — the flagship, general-purpose agent that ships in the car binary and works out of the box (car do).
browser_attention
Operator attention for a browser that is blocked waiting on a human sign-in — the host.event half of the browser drawer.
browser_relay
The agent→daemon browser hop: making a SUPERVISED AGENT PROCESS’s browser a first-class producer for the daemon’s crate::browser_view surface.
browser_view
The browser.view.* JSON-RPC surface — the browser drawer’s window onto a CAR browser.
channel
Channel identity + the inbound-channel seam (channel-agnostic, Unit 1/2/3).
channel_supervisor
Runtime channel supervisor + per-channel liveness (Units 1, 2, 3).
coder
Built-in coding agent (“CAR Coder”).
command_scheduler
Daemon-native command scheduler (#72).
evolution
Self-evolution governor — live daemon wiring (arXiv 2507.21046, the remaining daemon steps from docs/proposals/self-evolution-governor.md / docs/proposals/remaining-integration-work.md §3).
fanout
Multi-channel fan-out with one shared code (Unit 5 — MC-8).
feedback
The feedback.* JSON-RPC surface — CAR’s in-app feedback intake (PR A, wave 2, U4 of the plan in docs/plans/2026-08-31-car-feedback-system.md; outcomes contract docs/outcomes/car-feedback-system-outcomes.md).
feedback_drain
The feedback-spool drain — the background loop that uploads durable feedback submissions when connectivity and server capability allow.
fleet
fleet.* — the composite view of everything CAR can reach, and the placement layer that lets one Foreman run span several instances.
goal_suggest
handler
WebSocket connection handler — bidirectional JSON-RPC.
host
WS-coupled host pieces that stay in car-server-core after the #418 lift.
host_channel
Host-backed outbound channel adapter — how a channel CAR has no built-in transport for still gets delivered.
inference_control
Per-WebSocket inference lifecycle control.
inference_worker
On-device inference worker — process isolation for local MLX/Candle generation (Parslee-ai/car-releases#74).
mcp
MCP HTTP-streamable transport for the daemon.
mcp_assistant
The flagship assistant as three MCP tools: assistant_start, assistant_poll, assistant_cancel (car#972 §6).
mcp_daemon
Per-request MCP bridge into the real daemon dispatcher.
meeting
JSON wrappers for the meeting capability surface.
messaging_config
Per-channel approval-transport config + pairing store (Unit 2).
messaging_orchestrator
In-process iMessage approval-transport orchestrator (Units 2 & 4).
mobile_runtime
Parslee mobile runtime registration.
openrouter_auth
Daemon-owned OpenRouter OAuth PKCE flow.
parslee_auth
parslee_capabilities
parslee.capabilities — read-only discovery of what the signed-in Parslee account can do.
parslee_m365
m365 platform action tools, gated on the signed-in account’s entitlements.
parslee_tools
Agent-callable engine tools for the Parslee platform.
peers
Peer messaging between agents — agents.peers and agents.message.
permission_gate
Session permission-tier enforcement at proposal admission (Parslee-ai/car#890).
registry_reaper
Periodic reaper for the observe-only agent registry (~/.car/registry/*.json).
rpc_manifest
run_store
Disk-backed run-trace store (agent run tracing, U3).
run_trace
Per-turn run-trace recorder (agent run tracing, U2).
self_update
Self-update core + the default-on auto-update daemon task.
selfheal
Daemon wiring for deterministic self-healing detection and bounded PR fixes.
session
Server-side session state — shared across all connections.
slack_adapter
Slack approval-transport adapter (Unit 4) — the maximally-different SECOND channel that proves the channel-agnostic seam holds.
supervision
The admission gate, published as an out-of-process subscription.
sync
Daemon-held multi-device sync + execution-lease subsystem — the sync.* / lease.* WS surface’s engine (slice B6 of docs/proposals/multi-device-sync.md).
ui_agent_loop
Runtime-side convergence machinery for the UI-improvement loop.
voice_turn
FFI wrapper around car_engine::dispatch_voice_turn.
wire_schema
Deterministic release wire-schema generation and the server.schema payload.

Structs§

ApprovalCore
Channel-agnostic approval semantics over a shared HostState. Cheap to clone (just an Arc). One per adapter, or shared.
ChannelConfig
Per-channel trust state. The first three fields are exactly #403’s iMessage config (enabled, allowlisted_handles, active_pairing_code) — now held once per channel under crate::messaging_config::MessagingConfig::channels. The Slack-only slack_token_ref holds the keychain REFERENCE for that channel’s provisioned tokens (MC-9 — a ref, never a bearer), None for iMessage / an un-provisioned Slack channel.
ChannelLiveness
A point-in-time snapshot of one channel’s outbound-send health, recorded by the send path (U3) and read by messaging.status (U2). All fields are Option/bool so a never-sent channel reports cleanly (no send recorded).
ChannelSupervisor
Runtime supervisor for the approval-transport channels. Held as an Arc on crate::session::ServerState (lazy-initialized at boot by spawn_channel_pollers) so the host-gated messaging.config.set handler can reach it to spawn a channel’s watcher the instant the user enables it — no daemon/app restart (U1).
FanoutCoordinator
Multi-channel fan-out coordinator. Holds the channel-agnostic ApprovalCore (for the eligible-pending query), the shared code map, and the enabled channels’ OUTBOUND senders (iMessage orchestrator and/or Slack adapter). Either channel may be absent (only one enabled) — fan-out reduces to single-channel delivery, still through the one shared-code path.
MessagingOrchestrator
In-process iMessage adapter (re-homed from #403’s orchestrator). One per daemon; held behind an Arc and driven by its InboundChannel::run() poll loop. Cheap to clone the Arc. The channel-agnostic approval semantics live in ApprovalCore; this struct owns the iMessage-specific transport (chat.db poll, CodeMap text-code correlation, parse grammar).
RealMessageSender
Production send: routes through the un-gated plain Rust car_ffi_common::integrations::messages_send (integrations.rs:105) so the transport’s own send does NOT raise a messages.send approval and loop the gate. On non-macOS the underlying backend returns an Err at runtime (the symbol still links), so this builds on every platform.
SlackAdapter
In-process Slack adapter. UNCONDITIONAL (no #[cfg(target_os=...)] — MC-11): Slack is cross-platform, the whole point of the second channel proving the seam holds without macOS. Holds the channel-agnostic ApprovalCore (resolve by approval_id), the per-channel MessagingConfigStore (allowlist + pairing), the SlackTransport seam, and the configured Slack channel id to post into.
SlackTokenRef
A persisted, serializable reference to a channel’s tokens in the OS keychain (MC-9). It carries ONLY the keychain key NAMES the bearer values live under, never the xoxb-/xapp- strings themselves — so messaging.json holds a token reference, not a token. Its presence in a ChannelConfig doubles as the “tokens have been provisioned” marker (the adapter + UI can tell that credentials exist without reading them).
StampTransition
What stamping observed. Returned so the daemon can act on an upgrade instead of silently erasing the evidence of one.

Enums§

ChannelId
The closed set of approval channels. Exhaustively matched everywhere — no _ => wildcard (CLAUDE.md rule #2), so a future channel forces every match site to be revisited rather than silently swallowed.
ResolveOutcome
The outcome of a ApprovalCore::resolve call, so the calling adapter can decide whether to evict its code↔id mapping. Mirrors the #403 contract: a real resolve is Resolved; a fan-out non-resolve comes back Pending.
SlackInboundEvent
One inbound Slack event the adapter acts on. Closed set — the transport yields exactly one of these (or Ignore), so there is NO inbound→config-mutation edge by construction (MC-6). A config-mutation- shaped Slack message has no variant here and falls through to Ignore.

Constants§

HOST_MANAGEMENT_METHODS
JSON-RPC methods whose daemon handlers require host-management authority.

Traits§

InboundChannel
The inbound seam — the abstraction #403 never had. Each channel adapter implements this: it names its ChannelId and OWNS its own run loop, feeding observed messages into the supplied InboundSink. Object-safe via #[async_trait] (the cross-platform registry holds Box<dyn InboundChannel>).
InboundSink
The channel-agnostic inbound DELIVERY sink. An adapter feeds each inbound message it observes to deliver; the sink routes it to the host’s approval semantics (the iMessage adapter wires this to its handle_inbound). The boundary is delivery, NOT retrieval — InboundMessage carries only what handle_inbound reads (handle_id + body); the watermark stays private to the iMessage adapter’s poll loop and never crosses this sink.
MessageSender
Synchronous, injectable outbound-send seam. The production impl (RealMessageSender) calls the un-gated car_ffi_common::integrations::messages_send; tests substitute a capturing spy recording (handle, body) so SC-3/SC-5 assert the outbound behavior with no Messages.app.
SlackTransport
The Slack transport seam (MC-12 / MC-13). The production impl drives a Socket Mode WebSocket + the Web API; tests substitute a mock that captures outbound posts and injects inbound events.

Functions§

build_ack_frame
Build the Socket Mode ACK frame for an envelope. Pure function so the real transport and the wire-parse tests agree on the shape: the 3s-window ACK echoes ONLY the envelope_id back as the frame body (the minimal, no-response-payload ACK). Returns None when the envelope has no envelope_id (a frame that needs no ACK, e.g. hello/disconnect).
parse_events_api
Parse a Socket Mode events_api payload into a SlackInboundEvent::PairingDm, or None if it is not a member DM (the bot’s own echo is suppressed: subtype == "bot_message" or bot_id present). pub so the wire-parse + MC-6 gates exercise the REAL parser: a non-im channel message or a bot echo yields NoneIgnore.
parse_interactive
Parse a Socket Mode interactive (block_actions) payload into a SlackInboundEvent::ButtonInteraction, or None if it is not one of our two buttons. pub so the wire-parse gate (mc_slack_wire_parse) drives the REAL parser, not a pre-built enum — the MC-6 boundary lives in this code.
parse_socket_frame
Parse a top-level Socket Mode envelope (the WS text frame’s JSON) into a SlackInboundEvent. This is the SINGLE wire-parse entry point the real Socket Mode loop and the tests share: it routes by the envelope type (interactive → block_actions; events_api → message.im) and yields SlackInboundEvent::Ignore for everything else (the bot’s own echo, a non-DM channel message, an unknown action, a hello/disconnect frame).
parse_socket_url_response
Resolve the WebSocket URL out of an apps.connections.open response body. Pure function so the reconnect-spin guard is unit-testable without a live HTTP call: an ok:false body, or an ok:true body whose url is absent/empty, both yield Err (NOT Ok("")). Returning Ok("") would route through the success arm of RealSlackTransport::spawn_socket_loop (resetting backoff), then connect_async("") fails instantly — a tight, no-sleep open→fail→open spin. Routing it as Err sends it through the backoff/sleep arm instead.
spawn_channel_pollers
Spawn every ENABLED approval-transport adapter at daemon boot (Unit 3 — cross-platform registry). Iterates ChannelId::ALL; for each channel that is enabled in ~/.car/messaging.json it spawns that adapter’s InboundChannel::run loop on the shared cancel signal. The iMessage adapter alone is #[cfg(target_os = "macos")]-gated (it reads the local Messages library); the registry/trait/ChannelId are unconditional — there are NO cargo feature flags.
stamp_version
Read the existing stamp, write the succeeding one, and return both.
write_version_stamp
Write/refresh the version.json stamp under car_home. Called on daemon boot and by doctor --repair. Best-effort: a failure to stamp must never block startup, so the caller logs and continues.

Type Aliases§

SharedLiveness
Shared, lock-guarded per-channel liveness map. Written by the send path (U3) and read by messaging.status (U2). A std::sync::Mutex (not tokio) because every access is a tiny, non-await critical section.