lean_ctx/core/hive_gate.rs
1// SPDX-License-Identifier: Apache-2.0
2//! Whether this engine may use LeanCTX | Hive: the release switch, the preview
3//! switch for a loopback Hive, and the lines printed while Hive is off.
4//! The engine reads it to keep Hive tools and commands out of every list;
5//! the Hive connector re-exports it.
6
7/// Release switch: the connector shipped switched off in 3.12.0 and 3.12.1
8/// (`hive connect`/`hive link` refused, `hive` hidden from help, suggestions
9/// and completions). Owner 2026-11-04: LeanCTX | Hive opens with 3.12.2.
10pub const HIVE_AVAILABLE: bool = true;
11/// Test switch: `LEAN_CTX_HIVE_PREVIEW=1` opens the connector before the
12/// release, for a loopback Hive only (the FakeHive of the test suite).
13pub const PREVIEW_ENV: &str = "LEAN_CTX_HIVE_PREVIEW";
14/// The one line `hive connect`/`hive link` print while the switch is off.
15pub const NOT_AVAILABLE: &str =
16 "LeanCTX | Hive comes with 3.12.2; this version does not connect to a Hive.";
17/// The one line a call to a Hive MCP tool (`ctx_tasks`)
18/// answers while the switch is off; the tools stay out of every tool list.
19pub const TOOL_NOT_AVAILABLE: &str =
20 "LeanCTX | Hive comes with 3.12.2; this tool is not available in this version.";
21/// Hive MCP tools. They ship with the connector but follow its release switch
22/// ([`available_locally`], owner 28.10.): while it is off they are in no tool
23/// list and every call answers [`TOOL_NOT_AVAILABLE`].
24pub const HIVE_TOOLS: &[&str] = &["ctx_tasks"];
25
26fn preview() -> bool {
27 std::env::var(PREVIEW_ENV).as_deref() == Ok("1")
28}
29
30/// Whether `origin` names this machine (`127.0.0.1`, `localhost`, `::1`).
31pub fn is_loopback(origin: &str) -> bool {
32 let rest = origin
33 .strip_prefix("http://")
34 .or_else(|| origin.strip_prefix("https://"))
35 .unwrap_or(origin);
36 let host = if let Some(v6) = rest.strip_prefix('[') {
37 v6.split(']').next().unwrap_or_default()
38 } else {
39 rest.split(['/', ':']).next().unwrap_or_default()
40 };
41 matches!(host, "127.0.0.1" | "localhost" | "::1")
42}
43
44/// Whether this engine may connect to the Hive at `origin`.
45pub fn available_for(origin: &str) -> bool {
46 HIVE_AVAILABLE || (preview() && is_loopback(origin))
47}
48
49/// Whether Hive commands that name no origin (`hive link`) may run.
50pub fn available_locally() -> bool {
51 HIVE_AVAILABLE || preview()
52}