Complete runs a conversational AI completion with tool calling support.
(ctx context.Context, req *runtimev1.CompleteRequest)
| 204 | |
| 205 | // Complete runs a conversational AI completion with tool calling support. |
| 206 | func (s *Server) Complete(ctx context.Context, req *runtimev1.CompleteRequest) (resp *runtimev1.CompleteResponse, resErr error) { |
| 207 | // Access check |
| 208 | claims := auth.GetClaims(ctx, req.InstanceId) |
| 209 | if !claims.Can(runtime.UseAI) { |
| 210 | return nil, ErrForbidden |
| 211 | } |
| 212 | |
| 213 | // Apply configured timeout for AI completions |
| 214 | cfg, err := s.runtime.InstanceConfig(ctx, req.InstanceId) |
| 215 | if err != nil { |
| 216 | return nil, fmt.Errorf("failed to load instance config: %w", err) |
| 217 | } |
| 218 | ctx, cancel := context.WithTimeout(ctx, time.Duration(cfg.AICompletionTimeoutSeconds)*time.Second) |
| 219 | defer cancel() |
| 220 | |
| 221 | // Validate request - either prompt or feedback context must be provided |
| 222 | if req.Prompt == "" && req.FeedbackAgentContext == nil { |
| 223 | return nil, status.Error(codes.InvalidArgument, "prompt or feedback_agent_context must be provided") |
| 224 | } |
| 225 | |
| 226 | // Setup user agent |
| 227 | version := s.runtime.Version().Number |
| 228 | if version == "" { |
| 229 | version = "unknown" |
| 230 | } |
| 231 | userAgent := fmt.Sprintf("rill/%s", version) |
| 232 | |
| 233 | // Open the AI session |
| 234 | session, err := s.ai.Session(ctx, &ai.SessionOptions{ |
| 235 | InstanceID: req.InstanceId, |
| 236 | SessionID: req.ConversationId, |
| 237 | Claims: claims, |
| 238 | UserAgent: userAgent, |
| 239 | }) |
| 240 | if err != nil { |
| 241 | return nil, err |
| 242 | } |
| 243 | defer func() { |
| 244 | err := session.Flush(ctx) |
| 245 | if err != nil { |
| 246 | resErr = errors.Join(resErr, err) |
| 247 | } |
| 248 | }() |
| 249 | |
| 250 | // Prepare agent args if provided |
| 251 | var analystAgentArgs *ai.AnalystAgentArgs |
| 252 | if req.AnalystAgentContext != nil { |
| 253 | wherePerMetricsView := map[string]*metricsview.Expression{} |
| 254 | for m, e := range req.AnalystAgentContext.WherePerMetricsView { |
| 255 | wherePerMetricsView[m] = metricsview.NewExpressionFromProto(e) |
| 256 | } |
| 257 | |
| 258 | analystAgentArgs = &ai.AnalystAgentArgs{ |
| 259 | Explore: req.AnalystAgentContext.Explore, |
| 260 | Canvas: req.AnalystAgentContext.Canvas, |
| 261 | CanvasComponent: req.AnalystAgentContext.CanvasComponent, |
| 262 | WherePerMetricsView: wherePerMetricsView, |
| 263 | Dimensions: req.AnalystAgentContext.Dimensions, |