mirror of
https://github.com/azaion/autopilot.git
synced 2026-06-21 22:21:11 +00:00
[AZ-643] [AZ-665] [AZ-672] mavlink+mapobjects+vlm batch 4
ci/woodpecker/push/build-arm Pipeline failed
ci/woodpecker/push/build-arm Pipeline failed
AZ-643 mavlink_layer:
- ack demux on COMMAND_LONG/COMMAND_ACK with oneshot dispatch and
configurable deadline; MavlinkHandle::send_command + SendCommandError
- MAVLink-2 signing: Signer/Verifier built on SHA-256, key + timestamp
source, incompat-flag wiring in encoder, reject + counter in decoder
- new tests: tests/ack_demux.rs (3) + tests/signing.rs (5)
AZ-665 mapobjects_store:
- internal/h3_index.rs (h3o wrapper, cell_of, grid_disk, haversine)
- internal/store.rs (in-memory (cell -> Vec<MapObject>) hashmap with
k-ring classify and class-group resolution)
- public API: MapObjectsStoreHandle::classify(ClassifyInput) ->
Classification {New|Moved|Existing}
- AC1-4 in tests/classify.rs; AC5 perf gate (#[ignore], passes in
--release)
AZ-672 vlm_client + autopilot:
- DisabledVlmProvider in shared::contracts; VlmProvider::name() for
composition-root diagnostics
- vlm_client::VlmClient gated behind feature = "vlm"; placeholder
until AZ-673 lands the real NanoLLM IPC
- autopilot: vlm_client is now optional = true under feature vlm;
Runtime::select_vlm_provider picks DisabledVlmProvider when feature
off OR config.vlm.enabled = false
Workspace deps: +sha2 (mavlink signing), +h3o (mapobjects index).
Batch report: _docs/03_implementation/batch_04_cycle1_report.md
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -28,12 +28,44 @@ pub trait MavlinkSink: Send + Sync {
|
||||
async fn send_raw(&self, msg: Vec<u8>) -> Result<()>;
|
||||
}
|
||||
|
||||
/// Tier-3 visual-language-model provider. Default impl in `vlm_client` returns
|
||||
/// `VlmAssessment { status: Disabled, label: Inconclusive, ... }` when the
|
||||
/// `vlm` feature is off, satisfying the optionality contract.
|
||||
/// Tier-3 visual-language-model provider.
|
||||
///
|
||||
/// The default impl `DisabledVlmProvider` (also in this module) returns
|
||||
/// `VlmAssessment { status: Disabled, label: Inconclusive, ... }` and is
|
||||
/// the only path available when the binary is built without the `vlm`
|
||||
/// feature, or when `config.vlm.enabled = false` at runtime. The real
|
||||
/// IPC path lives in the optional `vlm_client` crate.
|
||||
#[async_trait]
|
||||
pub trait VlmProvider: Send + Sync {
|
||||
async fn assess(&self, roi: Vec<u8>, prompt: String) -> Result<VlmAssessment>;
|
||||
|
||||
/// Diagnostic name for the resolved provider. Used by the runtime
|
||||
/// composition root for `/health` and tracing. Implementations
|
||||
/// should return a stable kebab-case identifier; the default value
|
||||
/// is `"unknown"`.
|
||||
fn name(&self) -> &'static str {
|
||||
"unknown"
|
||||
}
|
||||
}
|
||||
|
||||
/// Zero-sized `VlmProvider` that always returns `VlmAssessment::disabled()`.
|
||||
///
|
||||
/// Available regardless of the `vlm` Cargo feature — `scan_controller` and
|
||||
/// the composition root depend only on `VlmProvider`, never on the
|
||||
/// optional `vlm_client` crate, so the binary can install this even when
|
||||
/// `vlm_client` is not compiled in.
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct DisabledVlmProvider;
|
||||
|
||||
#[async_trait]
|
||||
impl VlmProvider for DisabledVlmProvider {
|
||||
async fn assess(&self, _roi: Vec<u8>, _prompt: String) -> Result<VlmAssessment> {
|
||||
Ok(VlmAssessment::disabled())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"disabled"
|
||||
}
|
||||
}
|
||||
|
||||
/// Operator-command dispatch. Implemented by `operator_bridge`, fed by the
|
||||
@@ -42,3 +74,31 @@ pub trait VlmProvider: Send + Sync {
|
||||
pub trait OperatorCommandSink: Send + Sync {
|
||||
async fn dispatch(&self, command: OperatorCommand) -> Result<()>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::models::vlm::VlmStatus;
|
||||
|
||||
#[tokio::test]
|
||||
async fn ac1_disabled_provider_returns_disabled_status() {
|
||||
// Arrange
|
||||
let p = DisabledVlmProvider;
|
||||
|
||||
// Act
|
||||
let start = std::time::Instant::now();
|
||||
let result = p
|
||||
.assess(Vec::new(), String::new())
|
||||
.await
|
||||
.expect("disabled path is infallible");
|
||||
let elapsed = start.elapsed();
|
||||
|
||||
// Assert
|
||||
assert_eq!(result.status, VlmStatus::Disabled);
|
||||
assert!(
|
||||
elapsed <= std::time::Duration::from_millis(1),
|
||||
"expected ≤1 ms, got {elapsed:?}",
|
||||
);
|
||||
assert_eq!(p.name(), "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user