@@ -14,6 +14,7 @@ import (
|
||||
"data-terminal-cloud/internal/audit"
|
||||
"data-terminal-cloud/internal/embeddingprovider"
|
||||
"data-terminal-cloud/internal/retrieval"
|
||||
"data-terminal-cloud/internal/vikingmemory"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
@@ -39,6 +40,7 @@ type Response struct {
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
viking *vikingmemory.Service
|
||||
pool *pgxpool.Pool
|
||||
embedder embeddingprovider.Provider
|
||||
audit *audit.Repository
|
||||
@@ -46,7 +48,7 @@ type Service struct {
|
||||
}
|
||||
|
||||
type conversationScope struct {
|
||||
internalID, publicID, tenantID, subjectID, taskRef, engineMode, status string
|
||||
internalID, publicID, tenantID, subjectID, taskRef, engineMode, runtimeType, status string
|
||||
}
|
||||
|
||||
func NewService(pool *pgxpool.Pool, embedder embeddingprovider.Provider, auditRepository *audit.Repository) (*Service, error) {
|
||||
@@ -56,6 +58,8 @@ func NewService(pool *pgxpool.Pool, embedder embeddingprovider.Provider, auditRe
|
||||
return &Service{pool: pool, embedder: embedder, audit: auditRepository, now: time.Now}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ConfigureVikingMemory(memory *vikingmemory.Service) { s.viking = memory }
|
||||
|
||||
func (s *Service) Search(ctx context.Context, claims Claims, query string, limit int, requestID string) (Response, error) {
|
||||
started := s.now().UTC()
|
||||
query = strings.TrimSpace(query)
|
||||
@@ -68,6 +72,20 @@ func (s *Service) Search(ctx context.Context, claims Claims, query string, limit
|
||||
}
|
||||
digest := sha256.Sum256([]byte(query))
|
||||
queryDigest := hex.EncodeToString(digest[:])
|
||||
if s.viking != nil {
|
||||
searchContext, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
memories, searchErr := s.viking.Search(searchContext, scope.tenantID, scope.subjectID, query, limit)
|
||||
cancel()
|
||||
if searchErr == nil && len(memories) > 0 {
|
||||
items := make([]Result, 0, len(memories))
|
||||
for _, item := range memories {
|
||||
refs, _ := json.Marshal([]map[string]string{{"provider": "viking", "session_id": item.SessionID}})
|
||||
items = append(items, Result{MemoryID: item.ID, Content: item.Content, SourceRefs: refs, Relevance: item.Score})
|
||||
}
|
||||
s.recordCall(ctx, scope, queryDigest, len(items), "SUCCEEDED", "", started)
|
||||
return Response{Items: items}, nil
|
||||
}
|
||||
}
|
||||
embedding, err := s.embedder.Embed(ctx, query)
|
||||
if err != nil {
|
||||
s.recordCall(ctx, scope, queryDigest, 0, "FAILED", "EMBEDDING_UNAVAILABLE", started)
|
||||
@@ -126,16 +144,20 @@ func (s *Service) Search(ctx context.Context, claims Claims, query string, limit
|
||||
|
||||
func (s *Service) resolveScope(ctx context.Context, claims Claims) (conversationScope, error) {
|
||||
var scope conversationScope
|
||||
err := s.pool.QueryRow(ctx, `SELECT c.id::text,c.public_id::text,c.tenant_id::text,c.subject_id::text,rt.provider_task_ref,c.engine_mode,c.status
|
||||
FROM conversation c JOIN rtc_task rt ON rt.conversation_id=c.id WHERE c.public_id=$1::uuid`, claims.ConversationID).
|
||||
Scan(&scope.internalID, &scope.publicID, &scope.tenantID, &scope.subjectID, &scope.taskRef, &scope.engineMode, &scope.status)
|
||||
err := s.pool.QueryRow(ctx, `SELECT c.id::text,c.public_id::text,c.tenant_id::text,c.subject_id::text,
|
||||
COALESCE(rt.provider_task_ref,hs.provider_session_ref),c.engine_mode,c.runtime_type,c.status
|
||||
FROM conversation c
|
||||
LEFT JOIN rtc_task rt ON rt.conversation_id=c.id
|
||||
LEFT JOIN hardware_agent_session hs ON hs.conversation_id=c.id
|
||||
WHERE c.public_id=$1::uuid`, claims.ConversationID).
|
||||
Scan(&scope.internalID, &scope.publicID, &scope.tenantID, &scope.subjectID, &scope.taskRef, &scope.engineMode, &scope.runtimeType, &scope.status)
|
||||
if errors.Is(err, pgx.ErrNoRows) || scope.taskRef != claims.TaskRef {
|
||||
return conversationScope{}, ErrConversationUnavailable
|
||||
}
|
||||
if err != nil {
|
||||
return conversationScope{}, fmt.Errorf("resolve memory tool conversation: %w", err)
|
||||
}
|
||||
if scope.engineMode != "s2s_hybrid" {
|
||||
if scope.engineMode != "s2s_hybrid" && scope.runtimeType != "volc_hardware_agent" {
|
||||
return conversationScope{}, ErrEngineModeUnsupported
|
||||
}
|
||||
if scope.status != "ACTIVE" && scope.status != "STARTING_AGENT" {
|
||||
|
||||
Reference in New Issue
Block a user