Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/a365/hosting/turnContextUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function getCallerBaggagePairs(turnContext: TurnContextLike): Array<[stri
}
const from = turnContext.activity.from;
const pairs: Array<[string, string | undefined]> = [
[OpenTelemetryConstants.USER_ID_KEY, from.aadObjectId],
[OpenTelemetryConstants.USER_ID_KEY, from.aadObjectId || from.agenticUserId || from.id],
[OpenTelemetryConstants.USER_NAME_KEY, from.name],
[OpenTelemetryConstants.USER_EMAIL_KEY, from.agenticUserId],
[OpenTelemetryConstants.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, from.agenticAppBlueprintId],
Expand Down
1 change: 1 addition & 0 deletions src/a365/hosting/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface ActivityLike {
channelIdSubChannel?: string | unknown;
serviceUrl?: string;
from?: {
id?: string;
aadObjectId?: string;
name?: string;
role?: string;
Expand Down
54 changes: 54 additions & 0 deletions test/internal/unit/a365/hosting/turnContextUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,60 @@ describe("TurnContextUtils", () => {
expect(pairs).toEqual([]);
});

it("should fall back to from.id when aadObjectId is undefined (non-Teams channel)", () => {
const ctx: TurnContextLike = {
activity: {
from: { id: "webchat-user-123", name: "Web User" },
},
turnState: new Map(),
};
const pairs = getCallerBaggagePairs(ctx);
const obj = Object.fromEntries(pairs);
expect(obj[OpenTelemetryConstants.USER_ID_KEY]).toBe("webchat-user-123");
expect(obj[OpenTelemetryConstants.USER_NAME_KEY]).toBe("Web User");
});

it("should fall back to agenticUserId when aadObjectId is undefined (A2A)", () => {
const ctx: TurnContextLike = {
activity: {
from: { agenticUserId: "agent@contoso.com", name: "Upstream Agent" },
},
turnState: new Map(),
};
const pairs = getCallerBaggagePairs(ctx);
const obj = Object.fromEntries(pairs);
expect(obj[OpenTelemetryConstants.USER_ID_KEY]).toBe("agent@contoso.com");
});

it("should resolve userId to agenticUserId when it is a GUID (A2A with GUID)", () => {
const ctx: TurnContextLike = {
activity: {
from: { id: "29:1sH5NArUwkWAX", agenticUserId: "bef730f4-d6f5-4ffb-b759-26ffa449ed7e", name: "Agent" },
},
turnState: new Map(),
};
const pairs = getCallerBaggagePairs(ctx);
const obj = Object.fromEntries(pairs);
expect(obj[OpenTelemetryConstants.USER_ID_KEY]).toBe("bef730f4-d6f5-4ffb-b759-26ffa449ed7e");
});

it("should prefer aadObjectId over agenticUserId and from.id", () => {
const ctx: TurnContextLike = {
activity: {
from: {
id: "fallback-id",
aadObjectId: "aad-oid",
agenticUserId: "agent@contoso.com",
name: "User",
},
},
turnState: new Map(),
};
const pairs = getCallerBaggagePairs(ctx);
const obj = Object.fromEntries(pairs);
expect(obj[OpenTelemetryConstants.USER_ID_KEY]).toBe("aad-oid");
});

it("should filter out undefined/empty values", () => {
const ctx: TurnContextLike = {
activity: { from: { name: "User", aadObjectId: "" } },
Expand Down
Loading