MCPcopy Index your code
hub / github.com/coder/coder / ProcessRequest

Method ProcessRequest

aibridge/intercept/messages/blocking.go:70–343  ·  view source on GitHub ↗
(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

68}
69
70func (i *BlockingInterception) ProcessRequest(w http.ResponseWriter, r *http.Request) (outErr error) {
71 if len(i.reqPayload) == 0 {
72 return xerrors.New("developer error: request payload is empty")
73 }
74
75 ctx, span := i.tracer.Start(r.Context(), "Intercept.ProcessRequest", trace.WithAttributes(tracing.InterceptionAttributesFromContext(r.Context())...))
76 defer tracing.EndSpanErr(span, &outErr)
77
78 i.injectTools()
79
80 var prompt *string
81 promptText, promptFound, promptErr := i.reqPayload.lastUserPrompt()
82 if promptErr != nil {
83 i.logger.Warn(ctx, "failed to retrieve last user prompt", slog.Error(promptErr))
84 } else if promptFound {
85 prompt = &promptText
86 }
87
88 // TODO(ssncferreira): inject actor headers directly in the client-header
89 // middleware instead of using SDK options.
90 opts := []option.RequestOption{option.WithRequestTimeout(time.Second * 600)}
91 if actor := aibcontext.ActorFromContext(r.Context()); actor != nil && i.cfg.SendActorHeaders {
92 opts = append(opts, intercept.ActorHeadersAsAnthropicOpts(actor)...)
93 }
94
95 svc, err := i.newMessagesService(ctx, opts...)
96 if err != nil {
97 err = xerrors.Errorf("create anthropic client: %w", err)
98 http.Error(w, err.Error(), http.StatusInternalServerError)
99 return err
100 }
101
102 logger := i.logger.With(slog.F("model", i.Model()))
103
104 var resp *anthropic.Message
105 // Accumulate usage across the entire streaming interaction (including tool reinvocations).
106 var cumulativeUsage anthropic.Usage
107
108 for {
109 // TODO add outer loop span (https://github.com/coder/aibridge/issues/67)
110 resp, err = i.newMessage(ctx, svc)
111 if err != nil {
112 if eventstream.IsConnError(err) {
113 // Can't write a response, just error out.
114 return xerrors.Errorf("upstream connection closed: %w", err)
115 }
116
117 // The failover loop may return a keypool exhaustion
118 // error. Check before the SDK-error path.
119 var keyPoolErr *keypool.Error
120 if errors.As(err, &keyPoolErr) {
121 i.writeUpstreamError(w, ResponseErrorFromKeyPool(keyPoolErr))
122 return xerrors.Errorf("key pool exhausted: %w", err)
123 }
124
125 if antErr := responseErrorFromAPIError(err); antErr != nil {
126 i.writeUpstreamError(w, antErr)
127 return xerrors.Errorf("anthropic API error: %w", err)

Callers

nothing calls this directly

Calls 15

newMessageMethod · 0.95
EndSpanErrFunction · 0.92
IsConnErrorFunction · 0.92
accumulateUsageFunction · 0.85
newMessagesServiceMethod · 0.80
AsMethod · 0.80
CallMethod · 0.80
appendedMessagesMethod · 0.80
ResponseErrorFromKeyPoolFunction · 0.70

Tested by

no test coverage detected