Build an author from a delegated agent identity, if one is configured and resolvable. Returns `None` — rather than failing — whenever the identity is missing or unreadable. Recording a turn must not break because an agent identity was mistyped; falling back to the plus-tag author keeps the work attributed to someone* and leaves a debug log explaining why it is not keyed.
(options: &AgentAuthorOptions<'_>)
| 174 | /// mistyped; falling back to the plus-tag author keeps the work attributed to |
| 175 | /// *someone* and leaves a debug log explaining why it is not keyed. |
| 176 | fn delegated_agent_author(options: &AgentAuthorOptions<'_>) -> Option<Author> { |
| 177 | let name = options |
| 178 | .agent_identity |
| 179 | .clone() |
| 180 | .or_else(|| std::env::var(AGENT_IDENTITY_ENV).ok()) |
| 181 | .map(|n| n.trim().to_string()) |
| 182 | .filter(|n| !n.is_empty())?; |
| 183 | |
| 184 | let store = match options.identity_dir.as_deref() { |
| 185 | Some(dir) => atomic_identity::IdentityStore::open(dir), |
| 186 | None => atomic_identity::IdentityStore::open_default(), |
| 187 | } |
| 188 | .ok()?; |
| 189 | |
| 190 | let identity = match store.load_by_name(&name) { |
| 191 | Ok(identity) => identity, |
| 192 | Err(e) => { |
| 193 | log::debug!("Agent identity '{name}' not usable ({e}); falling back to plus-tag"); |
| 194 | return None; |
| 195 | } |
| 196 | }; |
| 197 | |
| 198 | // A human identity here would silently sign agent work as the human with |
| 199 | // no delegation behind it — worse than the plus-tag fallback, which at |
| 200 | // least does not claim to be keyed to an agent. |
| 201 | if !identity.identity_type.is_delegated() && !identity.identity_type.is_agent() { |
| 202 | log::debug!("'{name}' is not an agent identity; falling back to plus-tag"); |
| 203 | return None; |
| 204 | } |
| 205 | |
| 206 | let session_short = extract_session_short(options.session_id); |
| 207 | let tag = format!( |
| 208 | "{}+{}", |
| 209 | normalize_agent_name(options.agent_name), |
| 210 | session_short |
| 211 | ); |
| 212 | |
| 213 | Some(Author::with_identity( |
| 214 | &tag, |
| 215 | identity.email.clone(), |
| 216 | identity.public_key_base32(), |
| 217 | )) |
| 218 | } |
| 219 | |
| 220 | /// Derive the agent author from the user's identity. |
| 221 | /// |
no test coverage detected