1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Idempotency keys for LLM agent retries.
//!
//! When an agent retries a request — whether due to a 429, a timeout, or a
//! cache miss-aware policy ([cachebench](https://crates.io/crates/cachebench))
//! — the retry should carry the **same** idempotency key as the first
//! attempt so the server (or your dedup layer) recognizes it as a retry,
//! not a new request.
//!
//! `agentidemp` derives stable keys from the request content. Two flavors:
//!
//! - [`sha256_hex`] — short hex digest of the content, prefixed with `ik_`.
//! - [`uuid_v5`] — namespaced deterministic UUID, suitable for headers
//! that expect UUID format (e.g. `Idempotency-Key: <uuid>`).
//!
//! Plus [`random`] for the "I want a fresh key" case.
//!
//! # Quick start
//!
//! ```
//! use agentidemp::{sha256_hex, uuid_v5, NAMESPACE_ANTHROPIC};
//!
//! let body = serde_json::json!({"model": "claude", "messages": [{"role": "user", "content": "hi"}]});
//! let bytes = serde_json::to_vec(&body).unwrap();
//!
//! let k = sha256_hex(&bytes);
//! assert!(k.starts_with("ik_"));
//! assert_eq!(k.len(), 3 + 32); // ik_ + 32 hex chars
//!
//! let u = uuid_v5(&NAMESPACE_ANTHROPIC, &bytes);
//! assert_eq!(u.to_string().len(), 36);
//! ```
use ;
use Uuid;
/// A stable namespace UUID for Anthropic-bound requests. Use as the first
/// arg to [`uuid_v5`] to scope your keys.
pub const NAMESPACE_ANTHROPIC: Uuid = from_bytes;
// (NB: This is the standard DNS namespace UUID; we re-export it as a
// convenient anchor for users who don't want to think about namespaces.)
/// Compute a 16-byte sha256 prefix of `content`, hex-encoded, with the
/// `ik_` marker prefix. Useful for `Idempotency-Key` HTTP headers that
/// don't require a UUID format.
///
/// Returns a 35-character string (3 prefix + 32 hex).
/// Compute a deterministic [UUID v5][rfc] for `content` under `namespace`.
///
/// Same content + same namespace ⇒ same UUID, every time. Use this when
/// the destination expects a UUID-shaped idempotency key.
///
/// [rfc]: https://datatracker.ietf.org/doc/html/rfc4122#section-4.3
/// Generate a random UUID v4. For when you don't want determinism — e.g.
/// the very first attempt where you have no prior key to reuse.
/// Combine `scope` and `content` into a single hashed key. Useful when
/// the same content might recur across users/tenants and you want
/// per-scope deduplication.
///
/// Equivalent to `sha256_hex` over `scope || 0x00 || content`.