main
rs 51 lines 2.11 KB
Raw
1 //! The auth seam for products with a sign-in of their own.
2 //!
3 //! Without a provider the agent only knows terminal auth: a client runs `<agent> --setup`
4 //! and the key lands in the `env` file. A product whose credentials come from somewhere else
5 //! (a browser sign-in, a stored session) supplies an [`AuthProvider`] from
6 //! [`Profile::auth`](crate::Profile::auth) and the agent defers to it.
7
8 use agent_client_protocol::schema::v1::{AuthMethod, ClientCapabilities, RequestId};
9 use agent_client_protocol::{Client, ConnectionTo};
10 use async_trait::async_trait;
11
12 use crate::llm::LlmConfig;
13
14 /// What `authenticate` may use to reach the user.
15 pub struct AuthCtx<'a> {
16 /// The client connection, for a URL-mode elicitation or a notification.
17 pub connection: &'a ConnectionTo<Client>,
18 /// The `authenticate` request's own id. No session exists yet, so it scopes an
19 /// elicitation sent while the request is open.
20 pub request_id: RequestId,
21 /// What the client advertised in `initialize`, e.g. `elicitation.url`.
22 pub client_caps: &'a ClientCapabilities,
23 }
24
25 impl AuthCtx<'_> {
26 /// Whether the client can show a URL-mode elicitation.
27 pub fn client_offers_url_elicitation(&self) -> bool {
28 self.client_caps
29 .elicitation
30 .as_ref()
31 .is_some_and(|caps| caps.url.is_some())
32 }
33 }
34
35 #[async_trait]
36 pub trait AuthProvider: Send + Sync {
37 /// The method advertised in `initialize`, whatever the client's terminal capability,
38 /// e.g. `AuthMethod::Agent(AuthMethodAgent::new("sigit", "Sign in to siGit Code"))`.
39 fn method(&self) -> AuthMethod;
40
41 /// The stored session as an endpoint, a bearer and a model, or `None` when signed out.
42 /// Read before each session request, so a sign-in finished in this process or another
43 /// is picked up without a restart.
44 fn llm_config(&self) -> Option<LlmConfig>;
45
46 /// Run the sign-in. An existing session passes. An `Err` is shown to the user as is.
47 async fn authenticate(&self, ctx: AuthCtx<'_>) -> agent_client_protocol::Result<()>;
48
49 /// Forget the stored session.
50 async fn logout(&self) -> anyhow::Result<()>;
51 }