Compare commits
2 Commits
76038c43fd
...
71bc48449d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71bc48449d | ||
|
|
e5cb5e37ad |
@@ -10,6 +10,7 @@ import {
|
||||
CourseCategory,
|
||||
CourseCreateRequest,
|
||||
CourseUpdateRequest,
|
||||
GenerateCourseRequest,
|
||||
Enrollment,
|
||||
EnrollmentStatus,
|
||||
EnrollmentListResponse,
|
||||
@@ -273,6 +274,52 @@ export async function fetchAcademyStatistics(): Promise<AcademyStatistics> {
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COURSE GENERATION (via Training Engine)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* KI-gestuetzten Kurs generieren (nutzt intern Training Content Pipeline)
|
||||
*/
|
||||
export async function generateCourse(request: GenerateCourseRequest): Promise<Course> {
|
||||
return fetchWithTimeout<Course>(
|
||||
`${ACADEMY_API_BASE}/courses/generate`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request)
|
||||
},
|
||||
120000 // 2 min timeout for LLM generation
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Videos fuer alle Lektionen eines Kurses generieren
|
||||
*/
|
||||
export async function generateVideos(courseId: string): Promise<{ status: string; jobId?: string }> {
|
||||
return fetchWithTimeout<{ status: string; jobId?: string }>(
|
||||
`${ACADEMY_API_BASE}/courses/${courseId}/generate-videos`,
|
||||
{
|
||||
method: 'POST'
|
||||
},
|
||||
300000 // 5 min timeout for video generation
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Video-Generierungsstatus abrufen
|
||||
*/
|
||||
export async function getVideoStatus(courseId: string): Promise<{
|
||||
status: string
|
||||
total: number
|
||||
completed: number
|
||||
failed: number
|
||||
videos: Array<{ lessonId: string; status: string; url?: string }>
|
||||
}> {
|
||||
return fetchWithTimeout(
|
||||
`${ACADEMY_API_BASE}/courses/${courseId}/video-status`
|
||||
)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SDK PROXY FUNCTION (wraps fetchCourses + fetchAcademyStatistics)
|
||||
// =============================================================================
|
||||
|
||||
@@ -215,6 +215,15 @@ export interface CourseUpdateRequest {
|
||||
requiredForRoles?: string[]
|
||||
}
|
||||
|
||||
export interface GenerateCourseRequest {
|
||||
title: string
|
||||
category: CourseCategory
|
||||
description?: string
|
||||
regulationArea?: string
|
||||
language?: string
|
||||
durationMinutes?: number
|
||||
}
|
||||
|
||||
export interface EnrollUserRequest {
|
||||
courseId: string
|
||||
userId: string
|
||||
|
||||
@@ -292,11 +292,11 @@ export async function getModuleMedia(moduleId: string): Promise<{ media: Trainin
|
||||
}
|
||||
|
||||
export async function getMediaURL(mediaId: string): Promise<{ bucket: string; object_key: string; mime_type: string }> {
|
||||
return apiFetch(`/media/module/${mediaId}/url`)
|
||||
return apiFetch(`/media/${mediaId}/url`)
|
||||
}
|
||||
|
||||
export async function publishMedia(mediaId: string, publish?: boolean): Promise<{ status: string; is_published: boolean }> {
|
||||
return apiFetch(`/media/module/${mediaId}/publish`, {
|
||||
return apiFetch(`/media/${mediaId}/publish`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ publish: publish !== false }),
|
||||
})
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/academy"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/incidents"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/roadmap"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/training"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/ucca"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/whistleblower"
|
||||
"github.com/breakpilot/ai-compliance-sdk/internal/iace"
|
||||
@@ -69,6 +70,7 @@ func main() {
|
||||
incidentStore := incidents.NewStore(pool)
|
||||
vendorStore := vendor.NewStore(pool)
|
||||
iaceStore := iace.NewStore(pool)
|
||||
trainingStore := training.NewStore(pool)
|
||||
|
||||
// Initialize services
|
||||
rbacService := rbac.NewService(rbacStore)
|
||||
@@ -90,6 +92,10 @@ func main() {
|
||||
// Initialize PII detector
|
||||
piiDetector := llm.NewPIIDetectorWithPatterns(llm.AllPIIPatterns())
|
||||
|
||||
// Initialize TTS client and content generator for training
|
||||
ttsClient := training.NewTTSClient(cfg.TTSServiceURL)
|
||||
contentGenerator := training.NewContentGenerator(providerRegistry, piiDetector, trainingStore, ttsClient)
|
||||
|
||||
// Initialize access gate
|
||||
accessGate := llm.NewAccessGate(policyEngine, piiDetector, providerRegistry)
|
||||
|
||||
@@ -113,6 +119,7 @@ func main() {
|
||||
incidentHandlers := handlers.NewIncidentHandlers(incidentStore)
|
||||
vendorHandlers := handlers.NewVendorHandlers(vendorStore)
|
||||
iaceHandler := handlers.NewIACEHandler(iaceStore)
|
||||
trainingHandlers := handlers.NewTrainingHandlers(trainingStore, contentGenerator)
|
||||
|
||||
// Initialize middleware
|
||||
rbacMiddleware := rbac.NewMiddleware(rbacService, policyEngine)
|
||||
@@ -478,6 +485,74 @@ func main() {
|
||||
academyRoutes.GET("/stats", academyHandlers.GetStatistics)
|
||||
}
|
||||
|
||||
// Training Engine routes - Compliance Training Content Pipeline
|
||||
trainingRoutes := v1.Group("/training")
|
||||
{
|
||||
// Module CRUD
|
||||
trainingRoutes.GET("/modules", trainingHandlers.ListModules)
|
||||
trainingRoutes.GET("/modules/:id", trainingHandlers.GetModule)
|
||||
trainingRoutes.POST("/modules", trainingHandlers.CreateModule)
|
||||
trainingRoutes.PUT("/modules/:id", trainingHandlers.UpdateModule)
|
||||
|
||||
// Compliance Training Matrix (CTM)
|
||||
trainingRoutes.GET("/matrix", trainingHandlers.GetMatrix)
|
||||
trainingRoutes.GET("/matrix/:role", trainingHandlers.GetMatrixForRole)
|
||||
trainingRoutes.POST("/matrix", trainingHandlers.SetMatrixEntry)
|
||||
trainingRoutes.DELETE("/matrix/:role/:moduleId", trainingHandlers.DeleteMatrixEntry)
|
||||
|
||||
// Assignments
|
||||
trainingRoutes.POST("/assignments/compute", trainingHandlers.ComputeAssignments)
|
||||
trainingRoutes.GET("/assignments", trainingHandlers.ListAssignments)
|
||||
trainingRoutes.GET("/assignments/:id", trainingHandlers.GetAssignment)
|
||||
trainingRoutes.POST("/assignments/:id/start", trainingHandlers.StartAssignment)
|
||||
trainingRoutes.POST("/assignments/:id/progress", trainingHandlers.UpdateAssignmentProgress)
|
||||
trainingRoutes.POST("/assignments/:id/complete", trainingHandlers.CompleteAssignment)
|
||||
|
||||
// Quiz
|
||||
trainingRoutes.GET("/quiz/:moduleId", trainingHandlers.GetQuiz)
|
||||
trainingRoutes.POST("/quiz/:moduleId/submit", trainingHandlers.SubmitQuiz)
|
||||
trainingRoutes.GET("/quiz/attempts/:assignmentId", trainingHandlers.GetQuizAttempts)
|
||||
|
||||
// Content Generation (LLM)
|
||||
trainingRoutes.POST("/content/generate", trainingHandlers.GenerateContent)
|
||||
trainingRoutes.POST("/content/generate-quiz", trainingHandlers.GenerateQuiz)
|
||||
trainingRoutes.POST("/content/generate-all", trainingHandlers.GenerateAllContent)
|
||||
trainingRoutes.POST("/content/generate-all-quiz", trainingHandlers.GenerateAllQuizzes)
|
||||
trainingRoutes.GET("/content/:moduleId", trainingHandlers.GetContent)
|
||||
// PublishContent expects c.Param("id") but route uses :moduleId for Gin compatibility
|
||||
trainingRoutes.POST("/content/:moduleId/publish", func(c *gin.Context) {
|
||||
c.Params = append(c.Params, gin.Param{Key: "id", Value: c.Param("moduleId")})
|
||||
trainingHandlers.PublishContent(c)
|
||||
})
|
||||
|
||||
// Media (Audio/Video via TTS Service)
|
||||
trainingRoutes.POST("/content/:moduleId/generate-audio", trainingHandlers.GenerateAudio)
|
||||
trainingRoutes.POST("/content/:moduleId/generate-video", trainingHandlers.GenerateVideo)
|
||||
trainingRoutes.POST("/content/:moduleId/preview-script", trainingHandlers.PreviewVideoScript)
|
||||
trainingRoutes.GET("/media/module/:moduleId", trainingHandlers.GetModuleMedia)
|
||||
// Media detail routes use :mediaId consistently
|
||||
trainingRoutes.GET("/media/:mediaId/url", func(c *gin.Context) {
|
||||
c.Params = append(c.Params, gin.Param{Key: "id", Value: c.Param("mediaId")})
|
||||
trainingHandlers.GetMediaURL(c)
|
||||
})
|
||||
trainingRoutes.POST("/media/:mediaId/publish", func(c *gin.Context) {
|
||||
c.Params = append(c.Params, gin.Param{Key: "id", Value: c.Param("mediaId")})
|
||||
trainingHandlers.PublishMedia(c)
|
||||
})
|
||||
|
||||
// Deadlines & Escalation
|
||||
trainingRoutes.GET("/deadlines", trainingHandlers.GetDeadlines)
|
||||
trainingRoutes.GET("/deadlines/overdue", trainingHandlers.GetOverdueDeadlines)
|
||||
trainingRoutes.POST("/escalation/check", trainingHandlers.CheckEscalation)
|
||||
|
||||
// Audit & Statistics
|
||||
trainingRoutes.GET("/audit-log", trainingHandlers.GetAuditLog)
|
||||
trainingRoutes.GET("/stats", trainingHandlers.GetStats)
|
||||
|
||||
// Certificates
|
||||
trainingRoutes.GET("/certificates/:id/verify", trainingHandlers.VerifyCertificate)
|
||||
}
|
||||
|
||||
// Whistleblower routes - Hinweisgebersystem (HinSchG)
|
||||
whistleblowerRoutes := v1.Group("/whistleblower")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user