feat: initialize loyalty agent service structure, security configuration, and campaign MCP service orchestration
This commit is contained in:
@@ -2,7 +2,6 @@ package dev.sonpx.loyalty.agent.config;
|
||||
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -18,39 +17,10 @@ public class AgentConfig {
|
||||
2. When a tool result contains an `agent_instruction`, you MUST strictly follow its formatting rules when presenting the relevant data to the user. Do not output raw JSON data unless explicitly asked.
|
||||
""";
|
||||
|
||||
@Value("${loyalty.core.base-url}")
|
||||
private String coreBaseUrl;
|
||||
|
||||
@Bean
|
||||
public ChatClient loyaltyChatClient(ChatModel chatModel) {
|
||||
return ChatClient.builder(chatModel)
|
||||
.defaultSystem(AGENT_SYSTEM_PROMPT)
|
||||
.build();
|
||||
}
|
||||
|
||||
// @Bean
|
||||
// public RestClient coreRestClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||
// return RestClient.builder()
|
||||
// .baseUrl(coreBaseUrl)
|
||||
// .requestInterceptor((request, body, execution) -> {
|
||||
// org.springframework.security.core.Authentication principal =
|
||||
// new org.springframework.security.authentication.AnonymousAuthenticationToken(
|
||||
// "key", "loyalty-agent-service",
|
||||
// org.springframework.security.core.authority.AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
|
||||
// OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
|
||||
// .withClientRegistrationId("keycloak")
|
||||
// .principal(principal)
|
||||
// .build();
|
||||
// try {
|
||||
// OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(authorizeRequest);
|
||||
// if (authorizedClient != null && authorizedClient.getAccessToken() != null) {
|
||||
// request.getHeaders().setBearerAuth(authorizedClient.getAccessToken().getTokenValue());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return execution.execute(request, body);
|
||||
// })
|
||||
// .build();
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -12,33 +12,13 @@ import org.springframework.security.web.SecurityFilterChain;
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(authz -> authz
|
||||
.requestMatchers("/api/v1/agent/**", "/api/v1/conversations/**", "/ws/**", "/error").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
// .oauth2Login(Customizer.withDefaults())
|
||||
// .oauth2Client(Customizer.withDefaults());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
// @Bean
|
||||
// public OAuth2AuthorizedClientManager authorizedClientManager(
|
||||
// ClientRegistrationRepository clientRegistrationRepository,
|
||||
// OAuth2AuthorizedClientService authorizedClientService) {
|
||||
//
|
||||
// OAuth2AuthorizedClientProvider authorizedClientProvider =
|
||||
// OAuth2AuthorizedClientProviderBuilder.builder()
|
||||
// .clientCredentials()
|
||||
// .build();
|
||||
//
|
||||
// AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
|
||||
// new AuthorizedClientServiceOAuth2AuthorizedClientManager(
|
||||
// clientRegistrationRepository, authorizedClientService);
|
||||
// authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
||||
//
|
||||
// return authorizedClientManager;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -23,21 +23,6 @@ spring:
|
||||
connections:
|
||||
loyalty:
|
||||
url: ${MCP_SERVER_URL:http://localhost:9331}
|
||||
# security:
|
||||
# oauth2:
|
||||
# client:
|
||||
# registration:
|
||||
# keycloak:
|
||||
# client-id: ols-cli
|
||||
# client-secret: ${KEYCLOAK_CLIENT_SECRET:1jV8NSAeybIqmUK0AWhI8hgdo1q5itj7}
|
||||
# authorization-grant-type: client_credentials
|
||||
# provider:
|
||||
# keycloak:
|
||||
# token-uri: ${KEYCLOAK_TOKEN_URI:http://192.168.99.235/auth/realms/ols-cn-sit/protocol/openid-connect/token}
|
||||
|
||||
#loyalty:
|
||||
# core:
|
||||
# base-url: ${LOYALTY_CORE_BASE_URL:http://192.168.99.242:8081}
|
||||
|
||||
logging:
|
||||
pattern:
|
||||
|
||||
@@ -23,7 +23,23 @@ public class CampaignService {
|
||||
|
||||
public Result<List<Campaign>> getAll(CampaignCriteria criteria) {
|
||||
List<Campaign> campaigns = campaignClient.getAll(criteria, Pageable.ofSize(5));
|
||||
return Result.of(campaigns, "Format these campaigns as a markdown table with columns ID, Name, Start Date, End Date, Status.");
|
||||
return Result.of(campaigns, """
|
||||
Khi trả về danh sách chiến dịch, BẮT BUỘC KHÔNG dùng markdown table. Hãy định dạng theo cấu trúc sau:
|
||||
|
||||
1. **[Tên Chiến Dịch]** (ID: `[Mã ID]`)
|
||||
- 👤 Owner: [Tên Owner] (Nếu trống, ghi là: Không có)
|
||||
- 📝 Mô tả: [Mô tả] (Nếu trống, ghi là: Không có. Nếu dài hơn 100 ký tự, thêm "...")
|
||||
Ví dụ đầu ra ĐÚNG:
|
||||
1. **Happy Birthday!** (ID: `LACO`)
|
||||
- 👤 Owner: Không có
|
||||
- 📝 Mô tả: Không có
|
||||
2. **SummerSale GOTIT Campaign** (ID: `YZFG`)
|
||||
- 👤 Owner: Ngan Ha
|
||||
- 📝 Mô tả: Không có
|
||||
|
||||
Luôn kết thúc bằng một câu hỏi gợi mở để hướng dẫn người dùng bước tiếp theo.
|
||||
|
||||
""");
|
||||
}
|
||||
|
||||
public Result<Long> count(CampaignCriteria criteria) {
|
||||
|
||||
101
start-all.ps1
Normal file
101
start-all.ps1
Normal file
@@ -0,0 +1,101 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProjectRoot = $PSScriptRoot
|
||||
$LogDir = Join-Path $ProjectRoot "log"
|
||||
|
||||
if (-not (Test-Path $LogDir)) {
|
||||
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
|
||||
}
|
||||
|
||||
if (Test-Path (Join-Path $ProjectRoot ".env")) {
|
||||
Write-Host "Loading environment variables from .env"
|
||||
Get-Content (Join-Path $ProjectRoot ".env") | Where-Object { $_ -match "^[^#]" -and $_ -match "=" } | ForEach-Object {
|
||||
$name, $value = $_.Split("=", 2)
|
||||
[System.Environment]::SetEnvironmentVariable($name, $value)
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "=========================================="
|
||||
Write-Host "Cleaning up existing processes..."
|
||||
Write-Host "=========================================="
|
||||
foreach ($port in 9331, 9332, 9333) {
|
||||
$netstat = netstat -ano | Select-String "LISTENING" | Select-String ":$port"
|
||||
if ($netstat) {
|
||||
foreach ($line in $netstat) {
|
||||
$parts = $line -split '\s+'
|
||||
$pidToKill = $parts[-1]
|
||||
if ($pidToKill -and $pidToKill -ne "0") {
|
||||
Write-Host "Killing process on port $port (PID: $pidToKill)..."
|
||||
Stop-Process -Id $pidToKill -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ProcessList = @()
|
||||
|
||||
try {
|
||||
Write-Host "=========================================="
|
||||
Write-Host "Starting Loyalty Agent Services"
|
||||
Write-Host "=========================================="
|
||||
|
||||
# 1. Start MCP Server
|
||||
Write-Host "Starting loyalty-mcp-server..."
|
||||
$mcpLog = Join-Path $LogDir "loyalty-mcp-server.log"
|
||||
$mcpProcess = Start-Process -FilePath "cmd.exe" -ArgumentList "/c ..\mvnw.cmd spring-boot:run -Dmaven.test.skip=true > `"$mcpLog`" 2>&1" -WorkingDirectory (Join-Path $ProjectRoot "loyalty-mcp-server") -PassThru -WindowStyle Hidden
|
||||
$ProcessList += $mcpProcess
|
||||
Write-Host "loyalty-mcp-server started with PID: $($mcpProcess.Id)"
|
||||
|
||||
Write-Host "Waiting for loyalty-mcp-server to initialize..."
|
||||
while ($true) {
|
||||
$netstat = netstat -ano | Select-String "LISTENING" | Select-String ":9331"
|
||||
if ($netstat) { break }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
Write-Host "loyalty-mcp-server is up!"
|
||||
|
||||
# 2. Start Agent Service
|
||||
Write-Host "Starting loyalty-agent..."
|
||||
$agentLog = Join-Path $LogDir "loyalty-agent.log"
|
||||
$agentProcess = Start-Process -FilePath "cmd.exe" -ArgumentList "/c ..\mvnw.cmd spring-boot:run -Dmaven.test.skip=true > `"$agentLog`" 2>&1" -WorkingDirectory (Join-Path $ProjectRoot "loyalty-agent") -PassThru -WindowStyle Hidden
|
||||
$ProcessList += $agentProcess
|
||||
Write-Host "loyalty-agent started with PID: $($agentProcess.Id)"
|
||||
|
||||
Write-Host "Waiting for loyalty-agent to initialize..."
|
||||
while ($true) {
|
||||
$netstat = netstat -ano | Select-String "LISTENING" | Select-String ":9332"
|
||||
if ($netstat) { break }
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
Write-Host "loyalty-agent is up!"
|
||||
|
||||
# 3. Start Frontend UI
|
||||
Write-Host "Starting Frontend UI..."
|
||||
$uiLog = Join-Path $LogDir "frontend.log"
|
||||
$uiProcess = Start-Process -FilePath "cmd.exe" -ArgumentList "/c pnpm dev > `"$uiLog`" 2>&1" -WorkingDirectory $ProjectRoot -PassThru -WindowStyle Hidden
|
||||
$ProcessList += $uiProcess
|
||||
Write-Host "Frontend UI started with PID: $($uiProcess.Id)"
|
||||
|
||||
Write-Host "=========================================="
|
||||
Write-Host "All services started successfully!"
|
||||
Write-Host "Log files are stored in: $LogDir"
|
||||
Write-Host "- $mcpLog"
|
||||
Write-Host "- $agentLog"
|
||||
Write-Host "- $uiLog"
|
||||
Write-Host "=========================================="
|
||||
Write-Host "Press Ctrl+C to stop all services..."
|
||||
|
||||
# Wait indefinitely
|
||||
while ($true) {
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Write-Host "`nStopping services..."
|
||||
foreach ($p in $ProcessList) {
|
||||
if (-not $p.HasExited) {
|
||||
taskkill /PID $p.Id /T /F 2>&1 | Out-Null
|
||||
Write-Host "Stopped process tree for PID $($p.Id)"
|
||||
}
|
||||
}
|
||||
Write-Host "All services stopped."
|
||||
}
|
||||
Reference in New Issue
Block a user