-
Notifications
You must be signed in to change notification settings - Fork 8
Add Create User-Agent Header Utility #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Jesus Daniel Terrazas (JesuTerraz)
merged 19 commits into
main
from
users/jterrazas/add-user-agent-header
Dec 9, 2025
Merged
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d89e5b0
Add User-Agent header to util class
73c58b5
Use pkginfo to get pkg version
4bf11a6
update format
6025482
update test cases to work with github
e0764f7
cache version
f0c22fc
update nodejs version format
148aea2
copilot comments
df45069
Merge branch 'main' into users/jterrazas/add-user-agent-header
JesuTerraz 7413646
Remove OS parsing
681c7c7
Merge branch 'users/jterrazas/add-user-agent-header' of https://githu…
6f05c61
Merge branch 'main' into users/jterrazas/add-user-agent-header
7b82628
read package.json instead of modifying module.exports
267ca9a
remove cached version
da5c85b
Remove any pkginfo ref and use lazy init & cache version
b6a733a
Merge branch 'main' into users/jterrazas/add-user-agent-header
pontemonti a660b9d
Use prebuilt script to resolve version
ecbf63d
Remove duplicate tests
13efd81
Merge branch 'main' into users/jterrazas/add-user-agent-header
JesuTerraz 3343f01
Merge branch 'main' into users/jterrazas/add-user-agent-header
JesuTerraz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| import { Utility } from '@microsoft/agents-a365-runtime'; | ||
|
JesuTerraz marked this conversation as resolved.
Outdated
|
||
| import * as jwt from 'jsonwebtoken'; | ||
|
|
||
| describe('Utility', () => { | ||
| describe('GetAppIdFromToken', () => { | ||
| it('returns default GUID for empty token', () => { | ||
| // Arrange | ||
| const emptyToken = ''; | ||
| const undefinedToken = undefined as any; | ||
|
|
||
| // Act | ||
| const result1 = Utility.GetAppIdFromToken(emptyToken); | ||
| const result2 = Utility.GetAppIdFromToken(undefinedToken); | ||
|
|
||
| // Assert | ||
| expect(result1).toBe('00000000-0000-0000-0000-000000000000'); | ||
| expect(result2).toBe('00000000-0000-0000-0000-000000000000'); | ||
| }); | ||
|
|
||
| it('returns empty string for invalid token', () => { | ||
| // Arrange | ||
| const invalidToken = 'not-a-jwt'; | ||
|
|
||
| // Act | ||
| const result = Utility.GetAppIdFromToken(invalidToken); | ||
|
|
||
| // Assert | ||
| expect(result).toBe(''); | ||
| }); | ||
|
|
||
| it('returns appid claim if present', () => { | ||
| // Arrange | ||
| const payload = { appid: 'test-appid' }; | ||
| const token = jwt.sign(payload, 'secret'); | ||
|
|
||
| // Act | ||
| const result = Utility.GetAppIdFromToken(token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('test-appid'); | ||
| }); | ||
|
|
||
| it('returns azp claim if appid is missing', () => { | ||
| // Arrange | ||
| const payload = { azp: 'test-azp' }; | ||
| const token = jwt.sign(payload, 'secret'); | ||
|
|
||
| // Act | ||
| const result = Utility.GetAppIdFromToken(token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('test-azp'); | ||
| }); | ||
|
|
||
| it('returns empty string if neither appid nor azp', () => { | ||
| // Arrange | ||
| const payload = { foo: 'bar' }; | ||
| const token = jwt.sign(payload, 'secret'); | ||
|
|
||
| // Act | ||
| const result = Utility.GetAppIdFromToken(token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe(''); | ||
| }); | ||
| }); | ||
|
|
||
| describe('ResolveAgentIdentity', () => { | ||
| const createMockContext = (isAgentic: boolean, agenticId?: string) => ({ | ||
| activity: { | ||
| isAgenticRequest: () => isAgentic, | ||
| getAgenticInstanceId: () => agenticId, | ||
| }, | ||
| }) as any; | ||
|
|
||
| it('returns agentic instance ID if isAgenticRequest is true', () => { | ||
| // Arrange | ||
| const ctx = createMockContext(true, 'agentic-id-123'); | ||
| const token = 'token'; | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveAgentIdentity(ctx, token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('agentic-id-123'); | ||
| }); | ||
|
|
||
| it('returns empty string if isAgenticRequest is true but no agenticId', () => { | ||
| // Arrange | ||
| const ctx = createMockContext(true, undefined); | ||
| const token = 'token'; | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveAgentIdentity(ctx, token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe(''); | ||
| }); | ||
|
|
||
| it('falls back to GetAppIdFromToken if not agentic', () => { | ||
| // Arrange | ||
| const ctx = createMockContext(false); | ||
| const token = 'token'; | ||
| const spy = jest.spyOn(Utility, 'GetAppIdFromToken').mockReturnValue('fallback-id'); | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveAgentIdentity(ctx, token); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('fallback-id'); | ||
| spy.mockRestore(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('GetUserAgentHeader', () => { | ||
| it('returns string containing version, OS, and orchestrator', () => { | ||
| // Arrange | ||
| const orchestrator = 'orch'; | ||
|
|
||
| // Act | ||
| const header = Utility.GetUserAgentHeader(orchestrator); | ||
|
|
||
| // Assert | ||
| expect(header).toMatch(/Agent365SDK\/.+ (Windows|Linux|macOS|.+); Node\.js\/; orch/); | ||
| }); | ||
|
|
||
| it('works without orchestrator passed', () => { | ||
| // Arrange | ||
|
|
||
| // Act | ||
| const header = Utility.GetUserAgentHeader(); | ||
|
|
||
| // Assert | ||
| expect(header).toMatch(/Agent365SDK\/.+ (Windows|Linux|macOS|.+); Node\.js\/; /); | ||
| }); | ||
| }); | ||
|
|
||
| describe('ResolveOsType', () => { | ||
| afterEach(() => { | ||
| jest.resetModules(); | ||
| jest.clearAllMocks(); | ||
| }); | ||
|
|
||
| it('returns "Windows" for Windows_NT', () => { | ||
| // Arrange | ||
| jest.mock('os', () => ({ type: () => 'Windows_NT' }), { virtual: true }); | ||
| const { Utility } = require('@microsoft/agents-a365-runtime'); | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveOsType(); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('Windows'); | ||
| }); | ||
|
|
||
| it('returns "macOS" for Darwin', () => { | ||
| // Arrange | ||
| jest.mock('os', () => ({ type: () => 'Darwin' }), { virtual: true }); | ||
| const { Utility } = require('@microsoft/agents-a365-runtime'); | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveOsType(); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('macOS'); | ||
| }); | ||
|
|
||
| it('returns "Linux" for Linux', () => { | ||
| // Arrange | ||
| jest.mock('os', () => ({ type: () => 'Linux' }), { virtual: true }); | ||
| const { Utility } = require('@microsoft/agents-a365-runtime'); | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveOsType(); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('Linux'); | ||
| }); | ||
|
|
||
| it('returns type for unknown OS', () => { | ||
| // Arrange | ||
| jest.mock('os', () => ({ type: () => 'OtherOS' }), { virtual: true }); | ||
| const { Utility } = require('@microsoft/agents-a365-runtime'); | ||
|
|
||
| // Act | ||
| const result = Utility.ResolveOsType(); | ||
|
|
||
| // Assert | ||
| expect(result).toBe('OtherOS'); | ||
| }); | ||
| }); | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.