Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
51d2688
Initial commit
luis-gasparschroeder Sep 20, 2025
5c8f4ab
Added tests
luis-gasparschroeder Sep 20, 2025
24f6f60
Implemented endpoint
luis-gasparschroeder Sep 20, 2025
d69d9c0
Merged HyperionRepositoryStructureService into HyperionProgrammingExe…
luis-gasparschroeder Sep 23, 2025
b6ed7ca
Removed service annotation
luis-gasparschroeder Sep 23, 2025
13fe6e5
Added Service suffix
luis-gasparschroeder Sep 23, 2025
2eced3f
Updated API
luis-gasparschroeder Sep 23, 2025
4e7a2ab
Using signal
luis-gasparschroeder Sep 23, 2025
40e8f35
Moved getExistingSolutionCode to cenralized class
luis-gasparschroeder Sep 23, 2025
da81272
Moved getExistingSolutionCode to cenralized class
luis-gasparschroeder Sep 23, 2025
236bbe0
Implemented module auto generation
luis-gasparschroeder Sep 24, 2025
8473a1d
Fixed signal bug
luis-gasparschroeder Sep 25, 2025
1e1dc1f
Added service defintions (required for discovery)
luis-gasparschroeder Sep 26, 2025
525510c
Adjusted prompt injection to adhere to HyperionPromptTemplateService
luis-gasparschroeder Sep 26, 2025
0c171c7
Added i18n localization
luis-gasparschroeder Sep 26, 2025
9667bb4
Added documentation
luis-gasparschroeder Sep 26, 2025
53ecb19
Removed generateSolutionPlan duplicate
luis-gasparschroeder Sep 26, 2025
c78609c
Dependency injecting beans
luis-gasparschroeder Sep 26, 2025
3884102
Fixed creation assistance button alignment
luis-gasparschroeder Sep 26, 2025
1ea753f
Merge branch 'develop' into feature/hyperion/code-generation-clean
luis-gasparschroeder Sep 29, 2025
beb8b29
Added code generation documentation
luis-gasparschroeder Sep 29, 2025
978e204
Modified code generation documentation
luis-gasparschroeder Sep 30, 2025
c91763a
Hide code generation button when hyperion is disabled
luis-gasparschroeder Sep 30, 2025
2cb1ca4
Merge branch 'develop' into feature/hyperion/code-generation-clean
FelixTJDietrich Sep 30, 2025
ea8f9f6
Fix constructor calls in Hyperion test files
luis-gasparschroeder Oct 2, 2025
620a048
Merge branch 'feature/hyperion/code-generation-clean' of github.com:l…
luis-gasparschroeder Oct 2, 2025
595252a
Fixed DTO naming conventions
luis-gasparschroeder Oct 2, 2025
3416a0f
Added docstring
luis-gasparschroeder Oct 2, 2025
f1a1316
Fixed tests
luis-gasparschroeder Oct 2, 2025
433d89c
Added additional tests to increase code coverage
luis-gasparschroeder Oct 2, 2025
c0637bc
Adjusted jest config
luis-gasparschroeder Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,26 @@ paths:
content:
application/json:
schema: {$ref: '#/components/schemas/ProblemStatementRewriteResponse'}
/api/hyperion/programming-exercises/{exerciseId}/generate-code:
post:
tags: [hyperion-code-generation]
operationId: generateCode
parameters:
- name: exerciseId
in: path
required: true
schema: {type: integer, format: int64}
requestBody:
content:
application/json:
schema: {$ref: '#/components/schemas/CodeGenerationRequestDTO'}
required: true
responses:
'200':
description: OK
content:
application/json:
schema: {$ref: '#/components/schemas/CodeGenerationResultDTO'}
/api/tutorialgroup/tutorial-groups/{tutorialGroupId}/title:
get:
tags: [tutorial-group]
Expand Down Expand Up @@ -478,3 +498,23 @@ components:
registrationNumber: {type: string}
firstName: {type: string}
lastName: {type: string}
CodeGenerationRequestDTO:
type: object
description: Request DTO for code generation
properties:
repositoryType:
type: string
description: Type of repository to generate code for
enum: [TEMPLATE, SOLUTION, TESTS]
example: SOLUTION
CodeGenerationResultDTO:
type: object
description: Response DTO for code generation result
properties:
success: {type: boolean, description: Whether the code generation was successful,
example: true}
message: {type: string, description: Result message describing the outcome,
example: Solution code generated successfully and compiles without errors.}
attempts: {type: integer, format: int32, description: Number of generation
attempts made, example: 1}
required: [success, message, attempts]
54 changes: 54 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
"stylelint-config-standard": "39.0.0",
"stylelint-config-standard-scss": "16.0.0",
"stylelint-scss": "6.12.1",
"ts-morph": "27.0.0",
"typescript": "5.9.2",
"typescript-eslint": "8.44.1"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,37 @@ private void addDirectory(String containerId, String directoryName, boolean crea
}

private void copyToContainer(Path sourcePath, String containerId) {
try (final var uploadStream = new ByteArrayInputStream(createTarArchive(sourcePath).toByteArray());
final var copyToContainerCommand = buildAgentConfiguration.getDockerClient().copyArchiveToContainerCmd(containerId)
.withRemotePath(LOCAL_CI_DOCKER_CONTAINER_WORKING_DIRECTORY).withTarInputStream(uploadStream)) {
copyToContainerCommand.exec();
}
catch (IOException e) {
throw new LocalCIException("Could not copy to container " + containerId, e);
final int maxRetries = 3;
final long retryDelayMs = 1000;

/*
* Retry mechanism is essential for Docker container operations due to potential transient failures:
* - Docker daemon may be temporarily overloaded or unresponsive
* - Network connectivity issues between client and Docker daemon
* - Container filesystem may be temporarily locked or busy
* - Resource contention during concurrent build operations
* This improves reliability in CI/CD environments where multiple builds run simultaneously.
*/
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try (final var uploadStream = new ByteArrayInputStream(createTarArchive(sourcePath).toByteArray());
final var copyToContainerCommand = buildAgentConfiguration.getDockerClient().copyArchiveToContainerCmd(containerId)
.withRemotePath(LOCAL_CI_DOCKER_CONTAINER_WORKING_DIRECTORY).withTarInputStream(uploadStream)) {
copyToContainerCommand.exec();
return;
}
catch (Exception e) {
if (attempt == maxRetries) {
throw new LocalCIException("Could not copy to container " + containerId + " after " + maxRetries + " attempts", e);
}
log.warn("Attempt {} failed to copy to container {}: {}. Retrying in {} ms...", attempt, containerId, e.getMessage(), retryDelayMs);
try {
Thread.sleep(retryDelayMs);
}
catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new LocalCIException("Interrupted while retrying copy to container " + containerId, ie);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import com.fasterxml.jackson.annotation.JsonValue;

/**
* Enum for artifact types in consistency checks.
*/
public enum ArtifactType {
PROBLEM_STATEMENT, TEMPLATE_REPOSITORY, SOLUTION_REPOSITORY, TESTS_REPOSITORY

PROBLEM_STATEMENT("PROBLEM_STATEMENT"), TEMPLATE_REPOSITORY("TEMPLATE_REPOSITORY"), SOLUTION_REPOSITORY("SOLUTION_REPOSITORY"), TESTS_REPOSITORY("TESTS_REPOSITORY");

private final String value;

ArtifactType(String value) {
this.value = value;
}

@JsonValue
public String getValue() {
return value;
}

@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import jakarta.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonInclude;

import de.tum.cit.aet.artemis.programming.domain.RepositoryType;

/**
* DTO for requesting code generation for a programming exercise.
* Contains the repository type to determine which generation strategy to use.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationRequestDTO(@NotNull RepositoryType repositoryType) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;

/**
* DTO for internal code generation response.
* Contains the generated content from AI service calls.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationResponseDTO(
/**
* The solution plan as a string
*/
String solutionPlan,

/**
* List of generated files with path and content
*/
List<GeneratedFile> files) {

public String getSolutionPlan() {
return solutionPlan;
}

public List<GeneratedFile> getFiles() {
return files;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import com.fasterxml.jackson.annotation.JsonInclude;

/**
* DTO for REST API code generation result.
* Contains the result of the code generation and compilation process.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationResultDTO(
/**
* Whether the code generation and compilation was successful
*/
boolean success,

/**
* Descriptive message about the generation result
*/
String message,

/**
* Number of attempts made during the generation process
*/
int attempts) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package de.tum.cit.aet.artemis.hyperion.dto;

public record GeneratedFile(String path, String content) {
}
Loading
Loading