Skip to content

Commit b143d9e

Browse files
fix(run-templates): send plural array IDs to match API schema (#76)
The v1 API requires agent_ids/persona_ids/test_set_ids as arrays (min length 1), but the CLI was sending the singular variants and getting 400 INVALID_ARGUMENT on every create/update call. Flags are now repeatable or comma-delimited: coval run-templates create \ --agent-ids agentA,agentB \ --persona-ids p1 --persona-ids p2 \ --test-set-ids ts1
1 parent 8c7dc14 commit b143d9e

2 files changed

Lines changed: 44 additions & 39 deletions

File tree

src/client/models/run_template.rs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,26 @@ fn truncate(s: &str, max: usize) -> String {
1212
}
1313
}
1414

15+
fn summarize_ids(ids: &[String]) -> String {
16+
match ids.len() {
17+
0 => String::new(),
18+
1 => ids[0].clone(),
19+
n => format!("{} (+{})", ids[0], n - 1),
20+
}
21+
}
22+
1523
#[derive(Debug, Clone, Serialize, Deserialize)]
1624
pub struct RunTemplate {
1725
pub id: String,
1826
pub display_name: String,
1927
#[serde(default)]
2028
pub description: Option<String>,
21-
#[serde(skip_serializing_if = "Option::is_none")]
22-
pub agent_id: Option<String>,
23-
#[serde(skip_serializing_if = "Option::is_none")]
24-
pub persona_id: Option<String>,
25-
#[serde(skip_serializing_if = "Option::is_none")]
26-
pub test_set_id: Option<String>,
29+
#[serde(default)]
30+
pub agent_ids: Vec<String>,
31+
#[serde(default)]
32+
pub persona_ids: Vec<String>,
33+
#[serde(default)]
34+
pub test_set_ids: Vec<String>,
2735
#[serde(default)]
2836
pub metric_ids: Vec<String>,
2937
#[serde(default)]
@@ -50,12 +58,9 @@ pub struct CreateRunTemplateRequest {
5058
pub display_name: String,
5159
#[serde(skip_serializing_if = "Option::is_none")]
5260
pub description: Option<String>,
53-
#[serde(skip_serializing_if = "Option::is_none")]
54-
pub agent_id: Option<String>,
55-
#[serde(skip_serializing_if = "Option::is_none")]
56-
pub persona_id: Option<String>,
57-
#[serde(skip_serializing_if = "Option::is_none")]
58-
pub test_set_id: Option<String>,
61+
pub agent_ids: Vec<String>,
62+
pub persona_ids: Vec<String>,
63+
pub test_set_ids: Vec<String>,
5964
#[serde(skip_serializing_if = "Option::is_none")]
6065
pub metric_ids: Option<Vec<String>>,
6166
#[serde(skip_serializing_if = "Option::is_none")]
@@ -79,11 +84,11 @@ pub struct UpdateRunTemplateRequest {
7984
#[serde(skip_serializing_if = "Option::is_none")]
8085
pub description: Option<String>,
8186
#[serde(skip_serializing_if = "Option::is_none")]
82-
pub agent_id: Option<String>,
87+
pub agent_ids: Option<Vec<String>>,
8388
#[serde(skip_serializing_if = "Option::is_none")]
84-
pub persona_id: Option<String>,
89+
pub persona_ids: Option<Vec<String>>,
8590
#[serde(skip_serializing_if = "Option::is_none")]
86-
pub test_set_id: Option<String>,
91+
pub test_set_ids: Option<Vec<String>>,
8792
#[serde(skip_serializing_if = "Option::is_none")]
8893
pub metric_ids: Option<Vec<String>>,
8994
#[serde(skip_serializing_if = "Option::is_none")]
@@ -126,9 +131,9 @@ impl Tabular for RunTemplate {
126131
vec![
127132
"ID",
128133
"NAME",
129-
"AGENT",
130-
"PERSONA",
131-
"TEST SET",
134+
"AGENTS",
135+
"PERSONAS",
136+
"TEST SETS",
132137
"ITERATIONS",
133138
"CONCURRENCY",
134139
]
@@ -138,9 +143,9 @@ impl Tabular for RunTemplate {
138143
vec![
139144
self.id.clone(),
140145
truncate(&self.display_name, 25),
141-
self.agent_id.clone().unwrap_or_default(),
142-
self.persona_id.clone().unwrap_or_default(),
143-
self.test_set_id.clone().unwrap_or_default(),
146+
summarize_ids(&self.agent_ids),
147+
summarize_ids(&self.persona_ids),
148+
summarize_ids(&self.test_set_ids),
144149
self.iteration_count
145150
.map(|c| c.to_string())
146151
.unwrap_or_default(),

src/commands/run_templates.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ pub struct CreateArgs {
5555
name: Option<String>,
5656
#[arg(long)]
5757
description: Option<String>,
58-
#[arg(long)]
59-
agent_id: Option<String>,
60-
#[arg(long)]
61-
persona_id: Option<String>,
62-
#[arg(long)]
63-
test_set_id: Option<String>,
58+
#[arg(long, value_delimiter = ',')]
59+
agent_ids: Option<Vec<String>>,
60+
#[arg(long, value_delimiter = ',')]
61+
persona_ids: Option<Vec<String>>,
62+
#[arg(long, value_delimiter = ',')]
63+
test_set_ids: Option<Vec<String>>,
6464
#[arg(long, value_delimiter = ',')]
6565
metric_ids: Option<Vec<String>>,
6666
#[arg(long, value_delimiter = ',')]
@@ -84,12 +84,12 @@ pub struct UpdateArgs {
8484
name: Option<String>,
8585
#[arg(long)]
8686
description: Option<String>,
87-
#[arg(long)]
88-
agent_id: Option<String>,
89-
#[arg(long)]
90-
persona_id: Option<String>,
91-
#[arg(long)]
92-
test_set_id: Option<String>,
87+
#[arg(long, value_delimiter = ',')]
88+
agent_ids: Option<Vec<String>>,
89+
#[arg(long, value_delimiter = ',')]
90+
persona_ids: Option<Vec<String>>,
91+
#[arg(long, value_delimiter = ',')]
92+
test_set_ids: Option<Vec<String>>,
9393
#[arg(long, value_delimiter = ',')]
9494
metric_ids: Option<Vec<String>>,
9595
#[arg(long, value_delimiter = ',')]
@@ -155,9 +155,9 @@ pub async fn execute(
155155
let mut input = args.input_json.object()?;
156156
input_json::insert(&mut input, "display_name", args.name)?;
157157
input_json::insert(&mut input, "description", args.description)?;
158-
input_json::insert(&mut input, "agent_id", args.agent_id)?;
159-
input_json::insert(&mut input, "persona_id", args.persona_id)?;
160-
input_json::insert(&mut input, "test_set_id", args.test_set_id)?;
158+
input_json::insert(&mut input, "agent_ids", args.agent_ids)?;
159+
input_json::insert(&mut input, "persona_ids", args.persona_ids)?;
160+
input_json::insert(&mut input, "test_set_ids", args.test_set_ids)?;
161161
input_json::insert(&mut input, "metric_ids", args.metric_ids)?;
162162
input_json::insert(&mut input, "mutation_ids", args.mutation_ids)?;
163163
input_json::insert(&mut input, "iteration_count", args.iteration_count)?;
@@ -178,9 +178,9 @@ pub async fn execute(
178178
let mut input = args.input_json.object()?;
179179
input_json::insert(&mut input, "display_name", args.name)?;
180180
input_json::insert(&mut input, "description", args.description)?;
181-
input_json::insert(&mut input, "agent_id", args.agent_id)?;
182-
input_json::insert(&mut input, "persona_id", args.persona_id)?;
183-
input_json::insert(&mut input, "test_set_id", args.test_set_id)?;
181+
input_json::insert(&mut input, "agent_ids", args.agent_ids)?;
182+
input_json::insert(&mut input, "persona_ids", args.persona_ids)?;
183+
input_json::insert(&mut input, "test_set_ids", args.test_set_ids)?;
184184
input_json::insert(&mut input, "metric_ids", args.metric_ids)?;
185185
input_json::insert(&mut input, "mutation_ids", args.mutation_ids)?;
186186
input_json::insert(&mut input, "iteration_count", args.iteration_count)?;

0 commit comments

Comments
 (0)