Skip to content

Commit e4115f2

Browse files
fix(server): require positive model token bounds
1 parent dfc0515 commit e4115f2

6 files changed

Lines changed: 53 additions & 20 deletions

File tree

server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/catalog/CreateLlmModelRequestDTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package de.tum.cit.aet.hephaestus.agent.catalog;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.Min;
45
import jakarta.validation.constraints.NotBlank;
5-
import jakarta.validation.constraints.PositiveOrZero;
66
import jakarta.validation.constraints.Size;
77
import org.jspecify.annotations.NonNull;
88
import org.jspecify.annotations.Nullable;
@@ -21,10 +21,10 @@ public record CreateLlmModelRequestDTO(
2121
@NonNull @NotBlank @Size(max = 256) @Schema(description = "Upstream provider model id")
2222
String upstreamModelId,
2323

24-
@Nullable @PositiveOrZero @Schema(description = "Context window in tokens")
24+
@Nullable @Min(1) @Schema(description = "Context window in tokens")
2525
Integer contextWindow,
2626

27-
@Nullable @PositiveOrZero @Schema(description = "Maximum output tokens")
27+
@Nullable @Min(1) @Schema(description = "Maximum output tokens")
2828
Integer maxOutputTokens,
2929

3030
@Nullable @Schema(description = "Whether the model supports a reasoning mode")

server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/catalog/CreateWorkspaceLlmModelRequestDTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package de.tum.cit.aet.hephaestus.agent.catalog;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.Min;
45
import jakarta.validation.constraints.NotBlank;
5-
import jakarta.validation.constraints.PositiveOrZero;
66
import jakarta.validation.constraints.Size;
77
import java.math.BigDecimal;
88
import org.jspecify.annotations.NonNull;
@@ -22,10 +22,10 @@ public record CreateWorkspaceLlmModelRequestDTO(
2222
@NonNull @NotBlank @Size(max = 256) @Schema(description = "Upstream provider model id")
2323
String upstreamModelId,
2424

25-
@Nullable @PositiveOrZero @Schema(description = "Context window in tokens")
25+
@Nullable @Min(1) @Schema(description = "Context window in tokens")
2626
Integer contextWindow,
2727

28-
@Nullable @PositiveOrZero @Schema(description = "Maximum output tokens")
28+
@Nullable @Min(1) @Schema(description = "Maximum output tokens")
2929
Integer maxOutputTokens,
3030

3131
@Nullable @Schema(description = "Whether the model supports a reasoning mode")

server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/catalog/UpdateLlmModelRequestDTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package de.tum.cit.aet.hephaestus.agent.catalog;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4-
import jakarta.validation.constraints.PositiveOrZero;
4+
import jakarta.validation.constraints.Min;
55
import jakarta.validation.constraints.Size;
66
import org.jspecify.annotations.Nullable;
77

@@ -14,10 +14,10 @@ public record UpdateLlmModelRequestDTO(
1414
@Nullable @Size(max = 128) @Schema(description = "Human-readable name")
1515
String displayName,
1616

17-
@Nullable @PositiveOrZero @Schema(description = "Context window in tokens")
17+
@Nullable @Min(1) @Schema(description = "Context window in tokens")
1818
Integer contextWindow,
1919

20-
@Nullable @PositiveOrZero @Schema(description = "Maximum output tokens")
20+
@Nullable @Min(1) @Schema(description = "Maximum output tokens")
2121
Integer maxOutputTokens,
2222

2323
@Nullable @Schema(description = "Whether the model supports a reasoning mode")

server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/catalog/UpdateWorkspaceLlmModelRequestDTO.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package de.tum.cit.aet.hephaestus.agent.catalog;
22

33
import io.swagger.v3.oas.annotations.media.Schema;
4-
import jakarta.validation.constraints.PositiveOrZero;
4+
import jakarta.validation.constraints.Min;
55
import jakarta.validation.constraints.Size;
66
import java.math.BigDecimal;
77
import org.jspecify.annotations.Nullable;
@@ -18,10 +18,10 @@ public record UpdateWorkspaceLlmModelRequestDTO(
1818
@Nullable @Size(max = 128) @Schema(description = "Human-readable name")
1919
String displayName,
2020

21-
@Nullable @PositiveOrZero @Schema(description = "Context window in tokens")
21+
@Nullable @Min(1) @Schema(description = "Context window in tokens")
2222
Integer contextWindow,
2323

24-
@Nullable @PositiveOrZero @Schema(description = "Maximum output tokens")
24+
@Nullable @Min(1) @Schema(description = "Maximum output tokens")
2525
Integer maxOutputTokens,
2626

2727
@Nullable @Schema(description = "Whether the model supports a reasoning mode")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package de.tum.cit.aet.hephaestus.agent.catalog;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import de.tum.cit.aet.hephaestus.testconfig.BaseUnitTest;
6+
import jakarta.validation.Validation;
7+
import java.util.List;
8+
import java.util.function.IntFunction;
9+
import org.junit.jupiter.api.Test;
10+
11+
class LlmModelTokenBoundsTest extends BaseUnitTest {
12+
13+
private static final List<IntFunction<Object>> REQUESTS = List.of(
14+
value -> new CreateLlmModelRequestDTO(null, "Model", "model", value, value, null, null),
15+
value -> new UpdateLlmModelRequestDTO(null, value, value, null, null),
16+
value -> new CreateWorkspaceLlmModelRequestDTO(
17+
null, "Model", "model", value, value, null, null, null, null, null, null, null, null),
18+
value -> new UpdateWorkspaceLlmModelRequestDTO(
19+
null, value, value, null, null, null, null, null, null, null, null));
20+
21+
@Test
22+
void shouldRequirePositiveTokenBoundsForEveryModelRequest() {
23+
try (var factory = Validation.buildDefaultValidatorFactory()) {
24+
var validator = factory.getValidator();
25+
for (IntFunction<Object> request : REQUESTS) {
26+
assertThat(validator.validate(request.apply(0)))
27+
.extracting(violation -> violation.getPropertyPath().toString())
28+
.containsExactlyInAnyOrder("contextWindow", "maxOutputTokens");
29+
assertThat(validator.validate(request.apply(1))).isEmpty();
30+
}
31+
}
32+
}
33+
}

server/openapi.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8921,7 +8921,7 @@ components:
89218921
type: integer
89228922
format: int32
89238923
description: Context window in tokens
8924-
minimum: 0
8924+
minimum: 1
89258925
displayName:
89268926
type: string
89278927
description: Human-readable name
@@ -8934,7 +8934,7 @@ components:
89348934
type: integer
89358935
format: int32
89368936
description: Maximum output tokens
8937-
minimum: 0
8937+
minimum: 1
89388938
slug:
89398939
type: string
89408940
description: Optional internal slug; generated from displayName when omitted
@@ -9225,7 +9225,7 @@ components:
92259225
type: integer
92269226
format: int32
92279227
description: Context window in tokens
9228-
minimum: 0
9228+
minimum: 1
92299229
displayName:
92309230
type: string
92319231
description: Human-readable name
@@ -9238,7 +9238,7 @@ components:
92389238
type: integer
92399239
format: int32
92409240
description: Maximum output tokens
9241-
minimum: 0
9241+
minimum: 1
92429242
per1mCacheReadUsd:
92439243
type: number
92449244
format: decimal
@@ -15023,7 +15023,7 @@ components:
1502315023
type: integer
1502415024
format: int32
1502515025
description: Context window in tokens
15026-
minimum: 0
15026+
minimum: 1
1502715027
displayName:
1502815028
type: string
1502915029
description: Human-readable name
@@ -15036,7 +15036,7 @@ components:
1503615036
type: integer
1503715037
format: int32
1503815038
description: Maximum output tokens
15039-
minimum: 0
15039+
minimum: 1
1504015040
supportsReasoning:
1504115041
type: boolean
1504215042
description: Whether the model supports a reasoning mode
@@ -15414,7 +15414,7 @@ components:
1541415414
type: integer
1541515415
format: int32
1541615416
description: Context window in tokens
15417-
minimum: 0
15417+
minimum: 1
1541815418
displayName:
1541915419
type: string
1542015420
description: Human-readable name
@@ -15427,7 +15427,7 @@ components:
1542715427
type: integer
1542815428
format: int32
1542915429
description: Maximum output tokens
15430-
minimum: 0
15430+
minimum: 1
1543115431
per1mCacheReadUsd:
1543215432
type: number
1543315433
format: decimal

0 commit comments

Comments
 (0)