|
8 | 8 | InferenceOperationType, |
9 | 9 | InferenceScope, |
10 | 10 | InvokeAgentScope, |
| 11 | + InvokeAgentScopeDetails, |
11 | 12 | ObservabilityManager, |
| 13 | + Request, |
12 | 14 | TenantDetails, |
13 | 15 | } from "@microsoft/agents-a365-observability"; |
14 | 16 | import { ClusterCategory } from "@microsoft/agents-a365-runtime"; |
@@ -93,15 +95,21 @@ export class A365Agent extends AgentApplication<ApplicationTurnState> { |
93 | 95 | const baggageScope = new BaggageBuilder() |
94 | 96 | .tenantId(tenantDetails.tenantId) |
95 | 97 | .agentId(invokeAgentDetails.agentId) |
96 | | - .correlationId(uuidv4()) |
97 | 98 | .agentName(invokeAgentDetails.agentName) |
98 | 99 | .conversationId(context.activity.conversation?.id) |
99 | 100 | .build(); |
100 | 101 |
|
101 | 102 | await baggageScope.run(async () => { |
| 103 | + const request: Request = { |
| 104 | + conversationId: context.activity.conversation?.id, |
| 105 | + sessionId: context.activity.conversation?.id, |
| 106 | + content: context.activity.text || undefined, |
| 107 | + }; |
| 108 | + const invokeScopeDetails: InvokeAgentScopeDetails = {}; |
102 | 109 | const invokeAgentScope = InvokeAgentScope.start( |
103 | | - invokeAgentDetails, |
104 | | - tenantDetails |
| 110 | + request, |
| 111 | + invokeScopeDetails, |
| 112 | + { ...invokeAgentDetails, tenantId: tenantDetails.tenantId } |
105 | 113 | ); |
106 | 114 |
|
107 | 115 | await invokeAgentScope.withActiveSpanAsync(async () => { |
@@ -197,50 +205,62 @@ export class A365Agent extends AgentApplication<ApplicationTurnState> { |
197 | 205 |
|
198 | 206 | startTypingLoop(); |
199 | 207 |
|
| 208 | + let inferenceScope!: ReturnType<typeof InferenceScope.start>; |
200 | 209 | try { |
201 | 210 | const inferenceDetails: InferenceDetails = { |
202 | 211 | operationName: InferenceOperationType.CHAT, |
203 | 212 | model: "claude-3-7-sonnet-20250219", |
204 | 213 | providerName: "cognition-ai", |
205 | 214 | inputTokens: Math.ceil(userMessage.length / 4), // Rough estimate |
206 | | - responseId: `resp-${Date.now()}`, |
207 | 215 | outputTokens: 0, // Will be updated after response |
208 | 216 | finishReasons: undefined, |
209 | 217 | }; |
210 | 218 |
|
211 | | - const inferenceScope = InferenceScope.start( |
| 219 | + inferenceScope = InferenceScope.start( |
| 220 | + { conversationId: turnContext.activity.conversation?.id }, |
212 | 221 | inferenceDetails, |
213 | | - agentDetails, |
214 | | - tenantDetails |
| 222 | + { ...agentDetails, tenantId: agentDetails.tenantId || tenantDetails.tenantId } |
215 | 223 | ); |
216 | 224 | inferenceScope.recordInputMessages([userMessage]); |
217 | 225 |
|
| 226 | + const chunks: string[] = []; |
| 227 | + let streamErrorMessage: string | undefined; |
218 | 228 | let totalResponseLength = 0; |
219 | 229 | const responseStream = new Stream() |
220 | | - .on("data", async (chunk) => { |
221 | | - totalResponseLength += (chunk as string).length; |
222 | | - invokeAgentScope.recordOutputMessages([`LLM Response: ${chunk}`]); |
223 | | - inferenceScope.recordOutputMessages([`LLM Response: ${chunk}`]); |
224 | | - await turnContext.sendActivity(chunk); |
| 230 | + .on("data", (chunk) => { |
| 231 | + const text = chunk as string; |
| 232 | + totalResponseLength += text.length; |
| 233 | + chunks.push(text); |
| 234 | + invokeAgentScope.recordOutputMessages([`LLM Response: ${text}`]); |
| 235 | + inferenceScope.recordOutputMessages([`LLM Response: ${text}`]); |
225 | 236 | }) |
226 | | - .on("error", async (error) => { |
| 237 | + .on("error", (error) => { |
| 238 | + streamErrorMessage = String(error); |
227 | 239 | invokeAgentScope.recordOutputMessages([`Streaming error: ${error}`]); |
228 | 240 | inferenceScope.recordOutputMessages([`Streaming error: ${error}`]); |
229 | | - await turnContext.sendActivity(error); |
230 | 241 | }) |
231 | 242 | .on("close", () => { |
232 | | - inferenceScope.recordOutputTokens(Math.ceil(totalResponseLength / 4)); // Rough estimate |
| 243 | + inferenceScope.recordOutputTokens(Math.ceil(totalResponseLength / 4)); |
233 | 244 | inferenceScope.recordFinishReasons(["stop"]); |
234 | 245 | }); |
235 | 246 |
|
236 | 247 | await devinClient.invokeAgent(userMessage, responseStream); |
| 248 | + stopTypingLoop(); |
| 249 | + if (streamErrorMessage) { |
| 250 | + await turnContext.sendActivity("There was an error processing your request, please try again."); |
| 251 | + } else if (chunks.length > 0) { |
| 252 | + await turnContext.sendActivity(chunks.join("\n\n")); |
| 253 | + } else { |
| 254 | + await turnContext.sendActivity("Devin did not return a response. Please try again."); |
| 255 | + } |
237 | 256 | } catch (error) { |
| 257 | + stopTypingLoop(); |
238 | 258 | invokeAgentScope.recordOutputMessages([`LLM error: ${error}`]); |
239 | 259 | await turnContext.sendActivity( |
240 | 260 | "There was an error processing your request" |
241 | 261 | ); |
242 | 262 | } finally { |
243 | | - stopTypingLoop(); |
| 263 | + inferenceScope?.dispose(); |
244 | 264 | } |
245 | 265 | } |
246 | 266 |
|
|
0 commit comments