Commit 34293ca
authored
feat: Add AgentConfig, AgentConfigs, and JudgeConfig methods to ILdAiClient (#282)
## Summary
Adds the **public client surface** for agents and judges. Callers can
now ask `ILdAiClient` for agent configs (single or batch) and judge
configs in addition to the existing completion config.
Three new methods on `ILdAiClient` (and implementations on
`LdAiClient`):
### `AgentConfig`
```csharp
public LdAiAgentConfig AgentConfig(
string key,
Context context,
LdAiAgentConfigDefault defaultValue = null,
IReadOnlyDictionary<string, object> variables = null);
```
Single-agent retrieval. Mirrors `CompletionConfig`'s shape exactly —
same nullable-default semantics (null →
`LdAiAgentConfigDefault.Disabled`), same variable-interpolation contract
(`ldctx` is always available; user variables are merged in).
Emits a `$ld:ai:usage:agent-config` track event with `LdValue.Of(key)`
as the data and `1` as the metric value, matching the completion
telemetry shape.
### `AgentConfigs` (batch)
```csharp
public IReadOnlyDictionary<string, LdAiAgentConfig> AgentConfigs(
IEnumerable<AgentConfigRequest> agentConfigs,
Context context);
```
Batch retrieval. Each request is evaluated independently via
`BuildAgentConfig` (private helper — shared with the singular
`AgentConfig` method). The batch fires a **single**
`$ld:ai:usage:agent-configs` aggregate event with the request count as
both the data and the metric value. No individual
`$ld:ai:usage:agent-config` events are fired — the batch method
intentionally bypasses the public `AgentConfig` to avoid N+1 tracking
events.
`AgentConfigRequest` is a new public class with three settable
properties:
- `Key` — the agent config flag key.
- `DefaultValue` — the per-request fallback. When null, the per-call
`AgentConfig` invocation supplies `LdAiAgentConfigDefault.Disabled`.
- `Variables` — per-request template variables.
A null `agentConfigs` argument is treated as an empty enumerable (still
fires the aggregate event with count `0`).
### `JudgeConfig`
```csharp
public LdAiJudgeConfig JudgeConfig(
string key,
Context context,
LdAiJudgeConfigDefault defaultValue = null,
IReadOnlyDictionary<string, object> variables = null);
```
Single-judge retrieval. Same shape as `AgentConfig`. Emits
`$ld:ai:usage:judge-config`. No batched form — judges are evaluated one
at a time.
All three methods route through the same internal pipeline: track usage
event → `JsonVariation` (with the default's `ToLdValue()` as the
fallback) → the corresponding `ConfigFactory.Build*Config` method.
## Test plan
- [ ] `dotnet build` succeeds across `netstandard2.0`, `net462`,
`net8.0`
- [ ] `dotnet test --framework net8.0` passes
- [ ] `LdAiClientAgentJudgeTest` covers the agent surface:
- `AgentConfig_BasicRetrieval_ReturnsCorrectFields`
- `AgentConfig_ModeMismatch_ReturnsCallerDefault`
- `AgentConfig_InstructionsInterpolated`
- `AgentConfig_LdCtxInterpolatedInInstructions`
- `AgentConfig_FiresUsageEvent`
- `AgentConfigs_BatchRetrieval_ReturnsBothConfigs`
- `AgentConfigs_FiresIndividualAndAggregateEvents` (verifies the
per-request `$ld:ai:usage:agent-config` events **and** the single
`$ld:ai:usage:agent-configs` aggregate)
- `AgentConfigs_EmptyBatch_ReturnsEmptyAndFiresEvent`
- [ ] Same file covers the judge surface:
`JudgeConfig_BasicRetrieval_ReturnsCorrectFields`,
`JudgeConfig_ModeMismatch_ReturnsCallerDefault`,
`JudgeConfig_FiresUsageEvent`, `JudgeConfig_MessagesInterpolated`
- [ ] Reviewer confirms method signatures, default-value semantics, and
event names match the cross-SDK contract
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> New public SDK surface and usage-event contracts for AI config
retrieval; behavior follows existing CompletionConfig patterns but batch
telemetry differs from single-call semantics.
>
> **Overview**
> Extends **`ILdAiClient`** / **`LdAiClient`** with agent and judge
retrieval alongside existing completion config: **`AgentConfig`**, batch
**`AgentConfigs`**, and **`JudgeConfig`**, plus public
**`AgentConfigRequest`** (key, per-request default, variables).
>
> **`AgentConfig`** and **`JudgeConfig`** mirror **`CompletionConfig`**:
nullable defaults fall back to disabled types, **`JsonVariation`** +
**`ConfigFactory.Build*Config`**, Mustache variables with **`ldctx`**,
and per-call usage tracks (`$ld:ai:usage:agent-config`,
`$ld:ai:usage:judge-config`). **`AgentConfigs`** evaluates each request
via shared **`BuildAgentConfig`** (no per-key usage events), emits a
single **`$ld:ai:usage:agent-configs`** event with batch size, and maps
keys to configs (duplicate keys in the batch overwrite in the result
dictionary while the aggregate count still reflects every request).
>
> Tests in **`LdAiClientAgentJudgeTest`** and **`LdAiClientTest`** cover
retrieval, mode mismatch fallbacks, interpolation, and telemetry
behavior.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f30a2eb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 69418c8 commit 34293ca
5 files changed
Lines changed: 854 additions & 0 deletions
File tree
- pkgs/sdk/server-ai
- src
- Config
- Interfaces
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 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 | + | |
45 | 93 | | |
46 | 94 | | |
47 | 95 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
| |||
73 | 77 | | |
74 | 78 | | |
75 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
76 | 122 | | |
77 | 123 | | |
78 | 124 | | |
| |||
0 commit comments