@optimizely-opal/opal-tool-ocp-sdk 0.0.0-OCP-1487.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +631 -0
- package/dist/auth/AuthUtils.d.ts +31 -0
- package/dist/auth/AuthUtils.d.ts.map +1 -0
- package/dist/auth/AuthUtils.js +64 -0
- package/dist/auth/AuthUtils.js.map +1 -0
- package/dist/auth/AuthUtils.test.d.ts +2 -0
- package/dist/auth/AuthUtils.test.d.ts.map +1 -0
- package/dist/auth/AuthUtils.test.js +469 -0
- package/dist/auth/AuthUtils.test.js.map +1 -0
- package/dist/auth/TokenVerifier.d.ts +31 -0
- package/dist/auth/TokenVerifier.d.ts.map +1 -0
- package/dist/auth/TokenVerifier.js +127 -0
- package/dist/auth/TokenVerifier.js.map +1 -0
- package/dist/auth/TokenVerifier.test.d.ts +2 -0
- package/dist/auth/TokenVerifier.test.d.ts.map +1 -0
- package/dist/auth/TokenVerifier.test.js +125 -0
- package/dist/auth/TokenVerifier.test.js.map +1 -0
- package/dist/decorator/Decorator.d.ts +48 -0
- package/dist/decorator/Decorator.d.ts.map +1 -0
- package/dist/decorator/Decorator.js +53 -0
- package/dist/decorator/Decorator.js.map +1 -0
- package/dist/decorator/Decorator.test.d.ts +2 -0
- package/dist/decorator/Decorator.test.d.ts.map +1 -0
- package/dist/decorator/Decorator.test.js +528 -0
- package/dist/decorator/Decorator.test.js.map +1 -0
- package/dist/function/GlobalToolFunction.d.ts +28 -0
- package/dist/function/GlobalToolFunction.d.ts.map +1 -0
- package/dist/function/GlobalToolFunction.js +56 -0
- package/dist/function/GlobalToolFunction.js.map +1 -0
- package/dist/function/GlobalToolFunction.test.d.ts +2 -0
- package/dist/function/GlobalToolFunction.test.d.ts.map +1 -0
- package/dist/function/GlobalToolFunction.test.js +425 -0
- package/dist/function/GlobalToolFunction.test.js.map +1 -0
- package/dist/function/ToolFunction.d.ts +28 -0
- package/dist/function/ToolFunction.d.ts.map +1 -0
- package/dist/function/ToolFunction.js +60 -0
- package/dist/function/ToolFunction.js.map +1 -0
- package/dist/function/ToolFunction.test.d.ts +2 -0
- package/dist/function/ToolFunction.test.d.ts.map +1 -0
- package/dist/function/ToolFunction.test.js +314 -0
- package/dist/function/ToolFunction.test.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/service/Service.d.ts +80 -0
- package/dist/service/Service.d.ts.map +1 -0
- package/dist/service/Service.js +210 -0
- package/dist/service/Service.js.map +1 -0
- package/dist/service/Service.test.d.ts +2 -0
- package/dist/service/Service.test.d.ts.map +1 -0
- package/dist/service/Service.test.js +427 -0
- package/dist/service/Service.test.js.map +1 -0
- package/dist/types/Models.d.ts +126 -0
- package/dist/types/Models.d.ts.map +1 -0
- package/dist/types/Models.js +181 -0
- package/dist/types/Models.js.map +1 -0
- package/package.json +64 -0
- package/src/auth/AuthUtils.test.ts +586 -0
- package/src/auth/AuthUtils.ts +66 -0
- package/src/auth/TokenVerifier.test.ts +165 -0
- package/src/auth/TokenVerifier.ts +145 -0
- package/src/decorator/Decorator.test.ts +649 -0
- package/src/decorator/Decorator.ts +111 -0
- package/src/function/GlobalToolFunction.test.ts +505 -0
- package/src/function/GlobalToolFunction.ts +61 -0
- package/src/function/ToolFunction.test.ts +374 -0
- package/src/function/ToolFunction.ts +64 -0
- package/src/index.ts +5 -0
- package/src/service/Service.test.ts +661 -0
- package/src/service/Service.ts +213 -0
- package/src/types/Models.ts +163 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTokenVerifier = exports.TokenVerifier = void 0;
|
|
4
|
+
const jose_1 = require("jose");
|
|
5
|
+
const app_sdk_1 = require("@zaiusinc/app-sdk");
|
|
6
|
+
/**
|
|
7
|
+
* Default JWKS cache expiration time in milliseconds (1 hour)
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_JWKS_EXPIRES_IN = 60 * 60 * 1000;
|
|
10
|
+
/**
|
|
11
|
+
* Default clock skew tolerance in seconds
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_LEEWAY = 30;
|
|
14
|
+
/**
|
|
15
|
+
* Expected JWT audience for token validation
|
|
16
|
+
*/
|
|
17
|
+
const AUDIENCE = 'api://default';
|
|
18
|
+
/**
|
|
19
|
+
* Prep Base URL for Optimizely OAuth2 endpoints
|
|
20
|
+
*/
|
|
21
|
+
const PREP_BASE_URL = 'https://prep.login.optimizely.com/oauth2/default';
|
|
22
|
+
/**
|
|
23
|
+
* Prod Base URL for Optimizely OAuth2 endpoints
|
|
24
|
+
*/
|
|
25
|
+
const PROD_BASE_URL = 'https://login.optimizely.com/oauth2/default';
|
|
26
|
+
class TokenVerifier {
|
|
27
|
+
static instance = null;
|
|
28
|
+
jwksUri;
|
|
29
|
+
issuer;
|
|
30
|
+
jwks;
|
|
31
|
+
initialized = false;
|
|
32
|
+
/**
|
|
33
|
+
* Verify the provided Optimizely JWT token string
|
|
34
|
+
* @param token JWT token string to verify
|
|
35
|
+
* @returns boolean true if verification successful, false otherwise
|
|
36
|
+
* @throws Error if token is null, empty, or verifier is not properly configured
|
|
37
|
+
*/
|
|
38
|
+
async verify(token) {
|
|
39
|
+
if (!token || token.trim().length === 0) {
|
|
40
|
+
throw new Error('Token cannot be null or empty');
|
|
41
|
+
}
|
|
42
|
+
return this.verifyToken(token);
|
|
43
|
+
}
|
|
44
|
+
static getInstance() {
|
|
45
|
+
if (!TokenVerifier.instance) {
|
|
46
|
+
TokenVerifier.instance = new TokenVerifier();
|
|
47
|
+
}
|
|
48
|
+
return TokenVerifier.instance;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get singleton instance of TokenVerifier and ensure it's initialized
|
|
52
|
+
* @returns Promise<TokenVerifier> - initialized singleton instance
|
|
53
|
+
*/
|
|
54
|
+
static async getInitializedInstance() {
|
|
55
|
+
const instance = TokenVerifier.getInstance();
|
|
56
|
+
if (!instance.initialized) {
|
|
57
|
+
await instance.initialize();
|
|
58
|
+
}
|
|
59
|
+
return instance;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Initialize the TokenVerifier with discovery document from well-known endpoint
|
|
63
|
+
*/
|
|
64
|
+
async initialize() {
|
|
65
|
+
if (this.initialized) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
// Use prep URL when environment variable is set to 'staging', otherwise use prod
|
|
70
|
+
const environment = process.env.ENVIRONMENT || 'production';
|
|
71
|
+
const baseUrl = environment === 'staging' ? PREP_BASE_URL : PROD_BASE_URL;
|
|
72
|
+
const discoveryDocument = await this.fetchDiscoveryDocument(baseUrl);
|
|
73
|
+
this.issuer = discoveryDocument.issuer;
|
|
74
|
+
this.jwksUri = discoveryDocument.jwks_uri;
|
|
75
|
+
this.jwks = (0, jose_1.createRemoteJWKSet)(new URL(this.jwksUri), {
|
|
76
|
+
cacheMaxAge: DEFAULT_JWKS_EXPIRES_IN,
|
|
77
|
+
cooldownDuration: DEFAULT_JWKS_EXPIRES_IN
|
|
78
|
+
});
|
|
79
|
+
this.initialized = true;
|
|
80
|
+
app_sdk_1.logger.info(`TokenVerifier initialized with issuer: ${this.issuer} (environment: ${environment})`);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
app_sdk_1.logger.error('Failed to initialize TokenVerifier', error);
|
|
84
|
+
// Re-throw the original error to preserve specific error messages for tests
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Fetch discovery document from well-known endpoint
|
|
90
|
+
*/
|
|
91
|
+
async fetchDiscoveryDocument(baseUrl) {
|
|
92
|
+
const wellKnownUrl = `${baseUrl}/.well-known/oauth-authorization-server`;
|
|
93
|
+
const response = await fetch(wellKnownUrl);
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
throw new Error(`Failed to fetch discovery document: ${response.status} ${response.statusText}`);
|
|
96
|
+
}
|
|
97
|
+
const discoveryDocument = await response.json();
|
|
98
|
+
if (!discoveryDocument.issuer || !discoveryDocument.jwks_uri) {
|
|
99
|
+
throw new Error('Invalid discovery document: missing issuer or jwks_uri');
|
|
100
|
+
}
|
|
101
|
+
return discoveryDocument;
|
|
102
|
+
}
|
|
103
|
+
async verifyToken(token) {
|
|
104
|
+
if (!this.initialized) {
|
|
105
|
+
throw new Error('TokenVerifier not initialized. Call initialize() first.');
|
|
106
|
+
}
|
|
107
|
+
if (!this.jwks || !this.issuer) {
|
|
108
|
+
throw new Error('TokenVerifier not properly configured.');
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await (0, jose_1.jwtVerify)(token, this.jwks, {
|
|
112
|
+
issuer: this.issuer,
|
|
113
|
+
audience: AUDIENCE,
|
|
114
|
+
clockTolerance: DEFAULT_LEEWAY,
|
|
115
|
+
});
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
app_sdk_1.logger.error('Token verification failed:', error);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.TokenVerifier = TokenVerifier;
|
|
125
|
+
const getTokenVerifier = async () => TokenVerifier.getInitializedInstance();
|
|
126
|
+
exports.getTokenVerifier = getTokenVerifier;
|
|
127
|
+
//# sourceMappingURL=TokenVerifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenVerifier.js","sourceRoot":"","sources":["../../src/auth/TokenVerifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenVerifier.test.d.ts","sourceRoot":"","sources":["../../src/auth/TokenVerifier.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Mock the app-sdk module
|
|
4
|
+
jest.mock('@zaiusinc/app-sdk', () => ({
|
|
5
|
+
logger: {
|
|
6
|
+
info: jest.fn(),
|
|
7
|
+
error: jest.fn(),
|
|
8
|
+
warn: jest.fn(),
|
|
9
|
+
debug: jest.fn(),
|
|
10
|
+
},
|
|
11
|
+
}));
|
|
12
|
+
const TokenVerifier_1 = require("./TokenVerifier");
|
|
13
|
+
// Test constants
|
|
14
|
+
const TEST_ISSUER = 'https://prep.login.optimizely.com/oauth2/default';
|
|
15
|
+
const TEST_JWKS_URI = 'https://prep.login.optimizely.com/oauth2/v1/keys';
|
|
16
|
+
// Mock fetch globally
|
|
17
|
+
global.fetch = jest.fn();
|
|
18
|
+
describe('TokenVerifier', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
// Reset fetch mock
|
|
21
|
+
global.fetch.mockReset();
|
|
22
|
+
// Reset singleton instance for each test
|
|
23
|
+
TokenVerifier_1.TokenVerifier.instance = null;
|
|
24
|
+
});
|
|
25
|
+
describe('getInitializedInstance', () => {
|
|
26
|
+
it('should initialize successfully', async () => {
|
|
27
|
+
// Mock fetch for OAuth2 authorization server discovery
|
|
28
|
+
global.fetch.mockResolvedValue({
|
|
29
|
+
ok: true,
|
|
30
|
+
json: jest.fn().mockResolvedValue({
|
|
31
|
+
issuer: TEST_ISSUER,
|
|
32
|
+
jwks_uri: TEST_JWKS_URI
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
const tokenVerifier = await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
36
|
+
expect(tokenVerifier).toBeInstanceOf(TokenVerifier_1.TokenVerifier);
|
|
37
|
+
});
|
|
38
|
+
it('should throw error when discovery document is invalid', async () => {
|
|
39
|
+
global.fetch.mockResolvedValue({
|
|
40
|
+
ok: true,
|
|
41
|
+
json: jest.fn().mockResolvedValue({
|
|
42
|
+
// Missing issuer and jwks_uri
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
await expect(TokenVerifier_1.TokenVerifier.getInitializedInstance()).rejects.toThrow('Invalid discovery document: missing issuer or jwks_uri');
|
|
46
|
+
});
|
|
47
|
+
it('should throw error when discovery endpoint is unreachable', async () => {
|
|
48
|
+
global.fetch.mockResolvedValue({
|
|
49
|
+
ok: false,
|
|
50
|
+
status: 404,
|
|
51
|
+
statusText: 'Not Found'
|
|
52
|
+
});
|
|
53
|
+
await expect(TokenVerifier_1.TokenVerifier.getInitializedInstance()).rejects.toThrow('Failed to fetch discovery document: 404 Not Found');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('token verification', () => {
|
|
57
|
+
let tokenVerifier;
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
// Mock successful initialization
|
|
60
|
+
global.fetch.mockResolvedValue({
|
|
61
|
+
ok: true,
|
|
62
|
+
json: jest.fn().mockResolvedValue({
|
|
63
|
+
issuer: TEST_ISSUER,
|
|
64
|
+
jwks_uri: TEST_JWKS_URI
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
tokenVerifier = await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
68
|
+
});
|
|
69
|
+
it('should throw error for empty token', async () => {
|
|
70
|
+
await expect(tokenVerifier.verify('')).rejects.toThrow('Token cannot be null or empty');
|
|
71
|
+
});
|
|
72
|
+
it('should throw error for undefined token', async () => {
|
|
73
|
+
await expect(tokenVerifier.verify(undefined)).rejects.toThrow('Token cannot be null or empty');
|
|
74
|
+
});
|
|
75
|
+
it('should throw error for whitespace-only token', async () => {
|
|
76
|
+
await expect(tokenVerifier.verify(' ')).rejects.toThrow('Token cannot be null or empty');
|
|
77
|
+
});
|
|
78
|
+
it('should return false for invalid token format', async () => {
|
|
79
|
+
const result = await tokenVerifier.verify('invalid.jwt.token');
|
|
80
|
+
expect(result).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('singleton pattern', () => {
|
|
84
|
+
it('should return same instance when called multiple times', async () => {
|
|
85
|
+
// Mock successful initialization
|
|
86
|
+
global.fetch.mockResolvedValue({
|
|
87
|
+
ok: true,
|
|
88
|
+
json: jest.fn().mockResolvedValue({
|
|
89
|
+
issuer: TEST_ISSUER,
|
|
90
|
+
jwks_uri: TEST_JWKS_URI
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
const instance1 = await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
94
|
+
const instance2 = await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
95
|
+
expect(instance1).toBe(instance2);
|
|
96
|
+
});
|
|
97
|
+
it('should call correct prod OAuth2 authorization server discovery URL', async () => {
|
|
98
|
+
const fetchSpy = jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
99
|
+
ok: true,
|
|
100
|
+
json: jest.fn().mockResolvedValue({
|
|
101
|
+
issuer: TEST_ISSUER,
|
|
102
|
+
jwks_uri: TEST_JWKS_URI
|
|
103
|
+
})
|
|
104
|
+
});
|
|
105
|
+
await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
106
|
+
expect(fetchSpy).toHaveBeenCalledWith('https://login.optimizely.com/oauth2/default/.well-known/oauth-authorization-server');
|
|
107
|
+
});
|
|
108
|
+
it('should call correct prep OAuth2 authorization server discovery URL', async () => {
|
|
109
|
+
// Set environment variable to staging
|
|
110
|
+
process.env.ENVIRONMENT = 'staging';
|
|
111
|
+
const fetchSpy = jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
112
|
+
ok: true,
|
|
113
|
+
json: jest.fn().mockResolvedValue({
|
|
114
|
+
issuer: TEST_ISSUER,
|
|
115
|
+
jwks_uri: TEST_JWKS_URI
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
await TokenVerifier_1.TokenVerifier.getInitializedInstance();
|
|
119
|
+
expect(fetchSpy).toHaveBeenCalledWith('https://prep.login.optimizely.com/oauth2/default/.well-known/oauth-authorization-server');
|
|
120
|
+
// Clean up environment variable
|
|
121
|
+
delete process.env.ENVIRONMENT;
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=TokenVerifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenVerifier.test.js","sourceRoot":"","sources":["../../src/auth/TokenVerifier.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ParameterType } from '../types/Models';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for @tool decorator
|
|
4
|
+
*/
|
|
5
|
+
export interface ToolConfig {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
parameters: ParameterConfig[];
|
|
9
|
+
authRequirements?: AuthRequirementConfig[];
|
|
10
|
+
endpoint: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parameter configuration for decorators
|
|
14
|
+
*/
|
|
15
|
+
export interface ParameterConfig {
|
|
16
|
+
name: string;
|
|
17
|
+
type: ParameterType;
|
|
18
|
+
description: string;
|
|
19
|
+
required: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* AuthRequirement configuration for decorators
|
|
23
|
+
*/
|
|
24
|
+
export interface AuthRequirementConfig {
|
|
25
|
+
provider: string;
|
|
26
|
+
scopeBundle: string;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Configuration for @interaction decorator
|
|
31
|
+
*/
|
|
32
|
+
export interface InteractionConfig {
|
|
33
|
+
name: string;
|
|
34
|
+
endpoint: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Decorator for registering tool functions
|
|
38
|
+
* Immediately registers the tool with the global ToolsService
|
|
39
|
+
* The handler will have access to 'this' context when called
|
|
40
|
+
*/
|
|
41
|
+
export declare function tool(config: ToolConfig): (target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Decorator for registering interaction functions
|
|
44
|
+
* Immediately registers the interaction with the global ToolsService
|
|
45
|
+
* The handler will have access to 'this' context when called
|
|
46
|
+
*/
|
|
47
|
+
export declare function interaction(config: InteractionConfig): (target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
48
|
+
//# sourceMappingURL=Decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/Decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,IACrB,QAAQ,GAAG,EAAE,cAAc,MAAM,EAAE,YAAY,kBAAkB,UAkClF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,IACnC,QAAQ,GAAG,EAAE,cAAc,MAAM,EAAE,YAAY,kBAAkB,UAqBlF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tool = tool;
|
|
4
|
+
exports.interaction = interaction;
|
|
5
|
+
const Models_1 = require("../types/Models");
|
|
6
|
+
const Service_1 = require("../service/Service");
|
|
7
|
+
/**
|
|
8
|
+
* Decorator for registering tool functions
|
|
9
|
+
* Immediately registers the tool with the global ToolsService
|
|
10
|
+
* The handler will have access to 'this' context when called
|
|
11
|
+
*/
|
|
12
|
+
function tool(config) {
|
|
13
|
+
return function (target, _propertyKey, descriptor) {
|
|
14
|
+
// Convert parameter configs to Parameter instances
|
|
15
|
+
const parameters = (config.parameters || []).map((p) => new Models_1.Parameter(p.name, p.type, p.description, p.required));
|
|
16
|
+
// Convert auth requirement configs to AuthRequirement instances
|
|
17
|
+
const authRequirements = (config.authRequirements || []).map((a) => new Models_1.AuthRequirement(a.provider, a.scopeBundle, a.required));
|
|
18
|
+
const originalMethod = descriptor.value;
|
|
19
|
+
const boundHandler = function (functionContext, params, authData) {
|
|
20
|
+
// Check if we're being called from within a ToolFunction instance context
|
|
21
|
+
// If so, use that instance; otherwise create a new one
|
|
22
|
+
const instance = (functionContext && functionContext instanceof target.constructor) ?
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
24
|
+
functionContext : new target.constructor();
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
26
|
+
return originalMethod.call(instance, params, authData);
|
|
27
|
+
};
|
|
28
|
+
// Immediately register with global ToolsService
|
|
29
|
+
Service_1.toolsService.registerTool(config.name, config.description, boundHandler, parameters, config.endpoint, authRequirements);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Decorator for registering interaction functions
|
|
34
|
+
* Immediately registers the interaction with the global ToolsService
|
|
35
|
+
* The handler will have access to 'this' context when called
|
|
36
|
+
*/
|
|
37
|
+
function interaction(config) {
|
|
38
|
+
return function (target, _propertyKey, descriptor) {
|
|
39
|
+
const originalMethod = descriptor.value;
|
|
40
|
+
const boundHandler = function (functionContext, data, authData) {
|
|
41
|
+
// Check if we're being called from within a ToolFunction instance context
|
|
42
|
+
// If so, use that instance; otherwise create a new one
|
|
43
|
+
const instance = (functionContext && functionContext instanceof target.constructor) ?
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
45
|
+
functionContext : new target.constructor();
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
47
|
+
return originalMethod.call(instance, data, authData);
|
|
48
|
+
};
|
|
49
|
+
// Immediately register with global ToolsService
|
|
50
|
+
Service_1.toolsService.registerInteraction(config.name, boundHandler, config.endpoint);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=Decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Decorator.js","sourceRoot":"","sources":["../../src/decorator/Decorator.ts"],"names":[],"mappings":";;AA8CA,oBAmCC;AAOD,kCAsBC;AA9GD,4CAA4E;AAC5E,gDAAkD;AAwClD;;;;GAIG;AACH,SAAgB,IAAI,CAAC,MAAkB;IACrC,OAAO,UAAS,MAAW,EAAE,YAAoB,EAAE,UAA8B;QAC/E,mDAAmD;QACnD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrD,IAAI,kBAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CACzD,CAAC;QAEF,gEAAgE;QAChE,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjE,IAAI,wBAAe,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAC3D,CAAC;QAEF,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,MAAM,YAAY,GAAG,UAAS,eAAoB,EAAE,MAAW,EAAE,QAAa;YAC5E,0EAA0E;YAC1E,uDAAuD;YACvD,MAAM,QAAQ,GAAG,CAAC,eAAe,IAAI,eAAe,YAAY,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;gBACnF,6DAA6D;gBAC7D,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAE7C,6DAA6D;YAC7D,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACzD,CAAC,CAAC;QAEF,gDAAgD;QAChD,sBAAY,CAAC,YAAY,CACvB,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,WAAW,EAClB,YAAY,EACZ,UAAU,EACV,MAAM,CAAC,QAAQ,EACf,gBAAgB,CACjB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW,CAAC,MAAyB;IACnD,OAAO,UAAS,MAAW,EAAE,YAAoB,EAAE,UAA8B;QAC/E,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,MAAM,YAAY,GAAG,UAAS,eAAoB,EAAE,IAAS,EAAE,QAAc;YAC3E,0EAA0E;YAC1E,uDAAuD;YACvD,MAAM,QAAQ,GAAG,CAAC,eAAe,IAAI,eAAe,YAAY,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;gBACnF,6DAA6D;gBAC7D,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAE7C,6DAA6D;YAC7D,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvD,CAAC,CAAC;QAEF,gDAAgD;QAChD,sBAAY,CAAC,mBAAmB,CAC9B,MAAM,CAAC,IAAI,EACX,YAAY,EACZ,MAAM,CAAC,QAAQ,CAChB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Decorator.test.d.ts","sourceRoot":"","sources":["../../src/decorator/Decorator.test.ts"],"names":[],"mappings":""}
|