//// Persist capability and MCP choices while the runtime owns session reloads.
import albedo/harness/capability_catalog
import albedo/harness/extensions/mcp/extension as mcp
import gleam/option.{type Option}
import gleam/result
pub type Change {
Capability(kind: String, name: String, scope: String, enabled: Option(Bool))
Catalog(change: capability_catalog.Change)
MCP(name: String, server: Option(String), secrets: String)
}
pub fn mutate(
home: String,
session: String,
change: Change,
extensions: fn() -> Result(capability_catalog.Extensions, String),
after: fn() -> Result(a, String),
) -> Result(a, String) {
case change {
Catalog(change) ->
capability_catalog.save(
home,
session,
change,
extensions,
fn(kind, name) { enabling(session, kind, name) },
after,
)
Capability(kind, name, scope, enabled) ->
case
name != ""
&& { kind == "skills" || kind == "instructions" || kind == "mcp" }
&& { scope == "global" || scope == "session" }
{
True -> {
use _ <- result.try(case enabled {
option.Some(True) -> enabling(session, kind, name)
_ -> Ok(Nil)
})
capability(home, session, kind, name, #(scope, enabled), after)
}
False ->
Error("choose a capability kind, name, and global or session scope")
}
MCP(name, server, secrets) -> {
use _ <- result.try(mcp.validate_settings(name, server, secrets))
// Session preparation skips a server that is down; saving one refuses
// it, so a typo is caught where it is typed.
save_mcp(home, name, server, secrets, fn() {
use _ <- result.try(case server {
option.Some(_) -> mcp.check_connects(session, name, True)
option.None -> Ok(Nil)
})
after()
})
}
}
}
/// Turning a server on refuses one that cannot start; other kinds have
/// nothing to connect to.
fn enabling(
session: String,
kind: String,
name: String,
) -> Result(Nil, String) {
case kind {
"mcp" -> mcp.check_connects(session, name, False)
_ -> Ok(Nil)
}
}
@external(erlang, "albedo_settings_store", "capability")
fn capability(
home: String,
session: String,
kind: String,
name: String,
value: #(String, Option(Bool)),
after: fn() -> Result(a, String),
) -> Result(a, String)
@external(erlang, "albedo_settings_store", "mcp")
fn save_mcp(
home: String,
name: String,
server: Option(String),
secrets: String,
after: fn() -> Result(a, String),
) -> Result(a, String)