Skip to content

Commit 6019623

Browse files
committed
Fix a few things, do text similarity on endpoints
1 parent c6d5582 commit 6019623

File tree

32 files changed

+914
-637
lines changed

32 files changed

+914
-637
lines changed

.local.env

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
SENTRIUS_VERSION=1.1.375
1+
SENTRIUS_VERSION=1.1.411
22
SENTRIUS_SSH_VERSION=1.1.41
33
SENTRIUS_KEYCLOAK_VERSION=1.1.53
44
SENTRIUS_AGENT_VERSION=1.1.42
5-
SENTRIUS_AI_AGENT_VERSION=1.1.264
6-
LLMPROXY_VERSION=1.0.78
7-
LAUNCHER_VERSION=1.0.82
5+
SENTRIUS_AI_AGENT_VERSION=1.1.284
6+
LLMPROXY_VERSION=1.0.84
7+
LAUNCHER_VERSION=1.0.88
88
AGENTPROXY_VERSION=1.0.85
99
SSHPROXY_VERSION=1.0.88

.local.env.bak

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
SENTRIUS_VERSION=1.1.375
1+
SENTRIUS_VERSION=1.1.411
22
SENTRIUS_SSH_VERSION=1.1.41
33
SENTRIUS_KEYCLOAK_VERSION=1.1.53
44
SENTRIUS_AGENT_VERSION=1.1.42
5-
SENTRIUS_AI_AGENT_VERSION=1.1.264
6-
LLMPROXY_VERSION=1.0.78
7-
LAUNCHER_VERSION=1.0.82
5+
SENTRIUS_AI_AGENT_VERSION=1.1.284
6+
LLMPROXY_VERSION=1.0.84
7+
LAUNCHER_VERSION=1.0.88
88
AGENTPROXY_VERSION=1.0.85
9-
SSHPROXY_VERSION=1.0.87
9+
SSHPROXY_VERSION=1.0.88

agent-launcher/src/main/java/io/sentrius/agent/launcher/service/PodLauncherService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public V1Pod launchAgentPod(AgentRegistrationDTO agent) throws Exception {
178178
List<String> argList = new ArrayList<>();
179179
argList.add("--spring.config.location=file:/config/agent.properties");
180180
argList.add("--agent.namePrefix=" + agentId);
181-
argList.add("--agent.type=" + agent.getAgentType());
181+
argList.add("--agent.type=" + agentType);
182182
argList.add("--agent.clientId=" + agent.getClientId());
183183
argList.add("--agent.listen.websocket=true");
184184
argList.add("--agent.callback.url=" + constructedCallbackUrl);
@@ -203,6 +203,7 @@ public V1Pod launchAgentPod(AgentRegistrationDTO agent) throws Exception {
203203
argList.add("--agent.ai.config=/config/" + agentFile);
204204
}
205205

206+
log.info("Agent {} using config file: {}", agentId, argList);
206207

207208
String image = String.format("%ssentrius-launchable-agent:%s", myAgentRegistry, agentVersion);
208209

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package io.sentrius.agent.launcher.service;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Optional;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
import io.kubernetes.client.custom.IntOrString;
11+
import io.kubernetes.client.custom.Quantity;
12+
import io.kubernetes.client.openapi.ApiClient;
13+
import io.kubernetes.client.openapi.ApiException;
14+
import io.kubernetes.client.openapi.apis.CoreV1Api;
15+
import io.kubernetes.client.openapi.models.V1ConfigMapVolumeSource;
16+
import io.kubernetes.client.openapi.models.V1Container;
17+
import io.kubernetes.client.openapi.models.V1ObjectMeta;
18+
import io.kubernetes.client.openapi.models.V1Pod;
19+
import io.kubernetes.client.openapi.models.V1PodSpec;
20+
import io.kubernetes.client.openapi.models.V1PodStatus;
21+
import io.kubernetes.client.openapi.models.V1ResourceRequirements;
22+
import io.kubernetes.client.openapi.models.V1Service;
23+
import io.kubernetes.client.openapi.models.V1ServicePort;
24+
import io.kubernetes.client.openapi.models.V1ServiceSpec;
25+
import io.kubernetes.client.openapi.models.V1Volume;
26+
import io.kubernetes.client.openapi.models.V1VolumeMount;
27+
import io.kubernetes.client.util.Config;
28+
import io.sentrius.sso.core.dto.AgentRegistrationDTO;
29+
import io.sentrius.sso.core.model.AgentStatus;
30+
import lombok.extern.slf4j.Slf4j;
31+
import org.springframework.beans.factory.annotation.Value;
32+
import org.springframework.scheduling.annotation.Async;
33+
import org.springframework.scheduling.annotation.Scheduled;
34+
import org.springframework.stereotype.Service;
35+
36+
@Slf4j
37+
@Service
38+
public class PodMonitor {
39+
40+
private final CoreV1Api coreV1Api;
41+
42+
@Value("${sentrius.agent.registry}")
43+
private String agentRegistry;
44+
45+
@Value("${sentrius.agent.namespace}")
46+
private String agentNamespace;
47+
48+
public PodMonitor() throws IOException {
49+
ApiClient client = Config.defaultClient(); // in-cluster or kubeconfig
50+
this.coreV1Api = new CoreV1Api(client);
51+
}
52+
53+
@Scheduled(fixedDelay = 60000) // Runs every 60 seconds
54+
@Async
55+
public void removePodsInErrorState() throws ApiException {
56+
57+
log.info("Identifying pods to be removed");
58+
var pods = coreV1Api.listNamespacedPod(
59+
agentNamespace
60+
).execute().getItems();
61+
62+
List<V1Pod> podsToRemove = new ArrayList<>();
63+
for (V1Pod pod : pods) {
64+
65+
var podName = pod.getMetadata().getName();
66+
67+
if (podName == null || !podName.startsWith("sentrius-agent-")) {
68+
log.info("Skipping pod {}", podName);
69+
continue;
70+
}
71+
V1PodStatus status = pod.getStatus();
72+
if (status == null) {
73+
log.warn("Pod {} has no status information", podName);
74+
continue;
75+
}
76+
77+
String phase = status.getPhase(); // e.g., "Running", "Pending", "Failed", "Succeeded"
78+
if ("Error".equalsIgnoreCase(phase) || "Failed".equalsIgnoreCase(phase)) {
79+
log.info("Pod {} is in phase {}, adding to removal list", podName, phase);
80+
podsToRemove.add(pod);
81+
} else {
82+
log.info("Pod {} is in phase {}, skipping", podName, phase);
83+
}
84+
}
85+
86+
for (V1Pod pod : podsToRemove) {
87+
var podName = pod.getMetadata().getName();
88+
try {
89+
assert podName != null;
90+
coreV1Api.deleteNamespacedPod(
91+
podName,
92+
agentNamespace
93+
).execute();
94+
log.info("Deleted pod {}", podName);
95+
} catch (ApiException e) {
96+
log.error("Failed to delete pod {}: {}", podName, e.getResponseBody());
97+
}
98+
}
99+
100+
101+
}
102+
}

ai-agent/src/main/java/io/sentrius/agent/analysis/agents/agents/ChatAgent.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ public void onApplicationEvent(final ApplicationReadyEvent event) {
159159
PromptBuilder promptBuilder = new PromptBuilder(verbRegistry, config);
160160
var prompt = promptBuilder.buildPrompt(false);
161161
try {
162-
if (agentConfigOptions.getType().equalsIgnoreCase("chat-autonomous")) {
162+
if (null != agentConfigOptions.getType() && agentConfigOptions.getType().equalsIgnoreCase("chat" +
163+
"-autonomous")) {
163164

164165
response = chatVerbs.promptAgent(agentExecution, agentExecutionContext, prompt);
165166
}
@@ -170,7 +171,7 @@ public void onApplicationEvent(final ApplicationReadyEvent event) {
170171
}
171172

172173

173-
if (agentConfigOptions.getType().equalsIgnoreCase("chat-autonomous") && response == null) {
174+
if (null != agentConfigOptions.getType() && agentConfigOptions.getType().equalsIgnoreCase("chat-autonomous") && response == null) {
174175
log.error("Chat autonomous agent mode enabled but no response received from promptAgent, shutting down...");
175176
throw new RuntimeException("Chat autonomous agent mode enabled but no response received from promptAgent");
176177
}
@@ -184,7 +185,8 @@ public void onApplicationEvent(final ApplicationReadyEvent event) {
184185

185186
Thread.sleep(5_000);
186187
agentClientService.heartbeat(agentExecution, agentExecution.getUser().getUsername());
187-
if (agentConfigOptions.getType().equalsIgnoreCase("chat-autonomous")) {
188+
if (null != agentConfigOptions.getType() && agentConfigOptions.getType().equalsIgnoreCase("chat" +
189+
"-autonomous")) {
188190
log.info("Chat autonomous agent mode enabled, executing workload...");
189191
VerbResponse priorResponse = null;
190192
Map<String, Object> args = new HashMap<>();

ai-agent/src/main/java/io/sentrius/agent/analysis/agents/verbs/AgentVerbs.java

Lines changed: 31 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ public List<ZtatAsessment> analyzeAtatRequests(AgentExecution execution, List<At
590590
exampleJson = "{ \"context\": \"Notify when a new user is added\" }"
591591
)
592592
public AgentContextDTO createAgentContext(AgentExecution execution, AgentExecutionContextDTO context)
593-
throws ZtatException, JsonProcessingException {
593+
throws ZtatException, Exception {
594594
log.info("Creating agent context");
595595
var contextArgs = context.getExecutionArgs();
596596
if (contextArgs == null || contextArgs.isEmpty()) {
@@ -655,7 +655,19 @@ public AgentContextDTO createAgentContext(AgentExecution execution, AgentExecuti
655655
}
656656
var arrayNode = (ArrayNode) node.get("endpoints_like");
657657
for (JsonNode localNode : arrayNode) {
658-
endpointsLikeList.add(localNode.asText());
658+
if (localNode.isNull() || localNode.asText().isEmpty()) {
659+
continue;
660+
}
661+
if (localNode.has("method") && localNode.has("endpoint")) {
662+
663+
if (localNode.get("endpoint").asText().isEmpty() || localNode.get("method").asText().isEmpty()) {
664+
log.info("Skipping empty endpoint or method");
665+
continue;
666+
}
667+
668+
endpointsLikeList.add(localNode.asText());
669+
}
670+
659671
}
660672

661673
}
@@ -817,11 +829,12 @@ public ObjectNode getAgentStatus(AgentExecution execution, AgentExecutionContext
817829
@Verb(name = "get_endpoints_like", returnType = AgentExecutionContextDTO.class, description = "Queries for endpoints in " +
818830
"the system that match the input text." ,
819831
returnName = "endpoints",
820-
exampleJson = "{ \"endpoints_like\": [ \"listing users\", \"deleting users\" ] }",
832+
argName = "endpoints_like",
833+
exampleJson = "[ \"listing users\", \"deleting users\" ]",
821834
requiresTokenManagement = true )
822835
public ObjectNode getEndpointsLike(AgentExecution execution,
823836
AgentExecutionContextDTO executionContextDTO)
824-
throws ZtatException, JsonProcessingException {
837+
throws ZtatException, Exception {
825838

826839
var queryInput = executionContextDTO.getExecutionArgs();
827840
log.info("Querying for endpoints like: {}", queryInput);
@@ -848,97 +861,11 @@ public ObjectNode getEndpointsLike(AgentExecution execution,
848861
}
849862
contextNode.put("endpoints", endpoints);
850863

851-
/*
852-
var endpoints = verbRegistry.getEndpoints();
853-
ArrayNode endpointArray = JsonUtil.MAPPER.createArrayNode();
854-
for (var verb : endpoints) {
855-
if (verb.getPath() == null || verb.getPath().isEmpty()) {
856-
log.warn("Skipping verb {} with empty path", verb.getName());
857-
continue;
858-
}
859-
ObjectNode endpoint = JsonUtil.MAPPER.createObjectNode();
860-
endpoint.put("name", verb.getName());
861-
endpoint.put("description", verb.getDescription());
862-
endpoint.put("method", verb.getHttpMethod());
863-
ArrayNode parameters = JsonUtil.MAPPER.createArrayNode();
864-
if (verb.getParameters() != null) {
865-
for (var param : verb.getParameters()) {
866-
ObjectNode parameter = JsonUtil.MAPPER.createObjectNode();
867-
parameter.put("name", param.getName());
868-
parameter.put("description", param.getDescription());
869-
parameter.put("required", param.isRequired());
870-
parameter.put("type", param.getType());
871-
parameters.add(parameter);
872-
}
873-
}
874-
endpoint.put("parameters", parameters);
875-
var path = verb.getPath();
876-
if (verb.getServiceUrl() != null && !verb.getServiceUrl().isEmpty()) {
877-
if (path.startsWith("/")) {
878-
path = path.substring(1);
879-
}
880-
path = verb.getServiceUrl() + "/" + path;
881-
}
882-
endpoint.put("endpoint", path);
883-
endpointArray.add(endpoint);
884-
}
885-
*/
886-
/*
887-
var listedEndpoints = Message.builder().role("system").content("These are a list of available endpoints, " +
888-
"description," +
889-
" their " +
890-
"name. The user will provide a description of necessary actions. return endpoints that meet the " +
891-
"criteria with the name and endpoint in a json array. Endpoint may or may not contain a server url (ex : " +
892-
"[ { \"name\": " +
893-
"\"listUsers\", \"method\": \"GET\", \"endpoint\": \"https://server-url:8080/api/v1/users/list\" } ]:" + endpointArray).build();
894-
895-
contextNode.put("agentId", "agent1234");
896-
contextNode.put("status", "Running");
897-
List<Message> messages = new ArrayList<>();
898-
messages.add( listedEndpoints);
899-
900-
messages.add(Message.builder().role("user").content(queryInput.toString()).build());
901-
LLMRequest chatRequest = LLMRequest.builder().model("gpt-4o-mini").messages(messages).build();
902-
var resp = llmService.askQuestion(execution, chatRequest);
903-
904-
Response response = JsonUtil.MAPPER.readValue(resp, Response.class);
905-
// log.info("Response is {}", resp);
906-
for (Response.Choice choice : response.getChoices()) {
907-
var content = choice.getMessage().getContent();
908-
if (content.startsWith("```json")) {
909-
content = content.substring(7, content.length() - 3);
910-
} else if (content.startsWith("```")) {
911-
content = content.substring(3, content.length() - 3);
912-
}
913-
log.info("content is {}", content);
914-
if (null != content && !content.isEmpty()) {
915-
executionContextDTO.addMessages(choice.getMessage());
916-
try {
917-
918-
ObjectNode newResponse = JsonUtil.MAPPER.createObjectNode();
919-
JsonNode node = JsonUtil.MAPPER.readTree(content);
920-
921-
if (node.isArray()) {
922-
ArrayNode arrayNode = (ArrayNode) node;
923-
newResponse.put("endpoints", arrayNode);
924-
return newResponse;
925-
} else {
926-
log.warn("Expected JSON array but got: {}", node.getNodeType());
927-
}
928-
929-
return newResponse;
930-
}catch (JsonParseException e) {
931-
log.error("Failed to parse terminal response: {}", e.getMessage());
932-
throw e;
933-
}
934-
}
935-
}
936-
*/
937864
return contextNode;
938865
}
939866

940867
@Verb(name = "call_endpoint", returnType = AgentExecutionContextDTO.class, description = "Executes an endpoint at the " +
941-
"service. Input ", exampleJson = "{ \"endpoint\": \"url\", \"method\": \"httpMethod\", \"params\": { " +
868+
"service. Input ", exampleJson = "{ \"endpoint\": \"<url>\", \"method\": \"httpMethod\", \"params\": { " +
942869
"\"param1\": " +
943870
"\"param1Value\", " +
944871
"\"param2\": " +
@@ -1029,12 +956,23 @@ public ObjectNode callEndpoint(AgentExecution execution, AgentExecutionContextDT
1029956
throw new IllegalArgumentException("Unsupported method: " + method);
1030957
}
1031958

1032-
queryInput.addMessages(Message.builder().role("system").content("response from endpoint call: " + response).build());
959+
if (!isHtml(response)) {
960+
1033961

1034-
contextNode.put("response", response);
962+
queryInput.addMessages(
963+
Message.builder().role("system").content("response from endpoint call: " + response).build());
964+
965+
contextNode.put("response", response);
966+
} else {
967+
throw new RuntimeException("Received HTML response, likely an error page from " + endpoint);
968+
}
1035969
return contextNode;
1036970
}
1037971

972+
private boolean isHtml(String response){
973+
return response != null && (response.trim().startsWith("<!DOCTYPE html>") || response.trim().startsWith("<html"));
974+
}
975+
1038976
public String savePolicy(TokenDTO token, boolean includeDefault, ATPLPolicy policy) throws ZtatException {
1039977
try {
1040978

0 commit comments

Comments
 (0)