Skip to main content

kernel/config/
search.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! Which outside service a run's `web_search` reaches: the shape only.
7//!
8//! What `Default` points at, how `selected` is found, what a file may not
9//! say and on which rungs it may say it are all `city`'s answers
10//! (`crates/city/spec/ConfigLayers.lean` §8-4c, city D25), so the default
11//! supplier's address is declared there once and has no copy here.
12//!
13//! Specified by `crates/kernel/spec/Config.lean` §8-22.
14
15use serde::{Deserialize, Serialize};
16
17use crate::event::record::ProviderAccount;
18use crate::tool::ServerLabel;
19
20/// One search service reached over MCP streamable HTTP.
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
23pub struct SearchSupplier {
24    /// The supplier's name, and the Connector label `web_search` carries.
25    pub id: ServerLabel,
26    /// The MCP HTTP address, judged like an `[[mcp]]` url (city D26).
27    pub url: String,
28    /// The name of the remote tool in this supplier's `tools/list`.
29    pub remote: String,
30    /// The remote parameter `web_search`'s `query` is handed to.
31    pub query_field: String,
32    /// The remote parameter `objective` is handed to; `None` when this
33    /// supplier takes no objective.
34    pub objective_field: Option<String>,
35    /// The remote parameter `num_results` is handed to; `None` when this
36    /// supplier takes no count.
37    pub count_field: Option<String>,
38    /// In priority order. An anonymous account is the row without a
39    /// reference; a key appears only as its vault reference.
40    pub accounts: Vec<ProviderAccount>,
41}
42
43/// What a layer says about web search. Three arms and no `enabled`
44/// switch, so each of the three intents has one spelling: the default
45/// supplier, this supplier, none. `Default` is a stated value, not an
46/// absence: a layer that states it covers a farther layer's `Custom`.
47#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
50pub enum SearchConfiguration {
51    /// The supplier `city` declares as the default.
52    #[default]
53    Default,
54    /// Exactly the listed supplier whose id is `selected`; never another.
55    Custom {
56        selected: ServerLabel,
57        suppliers: Vec<SearchSupplier>,
58    },
59    /// No `web_search` under this layer.
60    Off,
61}