@memberjunction/ai 6.1.4 → 6.2.0-edge.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/dist/generic/baseDecision.d.ts +125 -0
- package/dist/generic/baseDecision.d.ts.map +1 -0
- package/dist/generic/baseDecision.js +387 -0
- package/dist/generic/baseDecision.js.map +1 -0
- package/dist/generic/baseImage.js +10 -10
- package/dist/generic/baseImage.js.map +1 -1
- package/dist/generic/baseLLM.d.ts +55 -1
- package/dist/generic/baseLLM.d.ts.map +1 -1
- package/dist/generic/baseLLM.js +44 -2
- package/dist/generic/baseLLM.js.map +1 -1
- package/dist/generic/baseModel.js +3 -3
- package/dist/generic/baseModel.js.map +1 -1
- package/dist/generic/baseRealtimeChannelServer.d.ts +1 -1
- package/dist/generic/baseRealtimeChannelServer.js +1 -1
- package/dist/generic/chat.types.d.ts +28 -0
- package/dist/generic/chat.types.d.ts.map +1 -1
- package/dist/generic/chat.types.js +51 -11
- package/dist/generic/chat.types.js.map +1 -1
- package/dist/generic/classify.types.d.ts +11 -0
- package/dist/generic/classify.types.d.ts.map +1 -1
- package/dist/generic/classify.types.js +11 -0
- package/dist/generic/classify.types.js.map +1 -1
- package/dist/generic/decision.types.d.ts +201 -0
- package/dist/generic/decision.types.d.ts.map +1 -0
- package/dist/generic/decision.types.js +29 -0
- package/dist/generic/decision.types.js.map +1 -0
- package/dist/generic/errorAnalyzer.d.ts +2 -0
- package/dist/generic/errorAnalyzer.d.ts.map +1 -1
- package/dist/generic/errorAnalyzer.js +17 -8
- package/dist/generic/errorAnalyzer.js.map +1 -1
- package/dist/generic/linearTextScan.d.ts +18 -0
- package/dist/generic/linearTextScan.d.ts.map +1 -0
- package/dist/generic/linearTextScan.js +70 -0
- package/dist/generic/linearTextScan.js.map +1 -0
- package/dist/generic/modelConfiguration.d.ts +68 -3
- package/dist/generic/modelConfiguration.d.ts.map +1 -1
- package/dist/generic/modelConfiguration.js +26 -5
- package/dist/generic/modelConfiguration.js.map +1 -1
- package/dist/generic/openAICompatibleTools.d.ts +10 -0
- package/dist/generic/openAICompatibleTools.d.ts.map +1 -1
- package/dist/generic/openAICompatibleTools.js +27 -7
- package/dist/generic/openAICompatibleTools.js.map +1 -1
- package/dist/generic/summarize.types.d.ts +7 -0
- package/dist/generic/summarize.types.d.ts.map +1 -1
- package/dist/generic/summarize.types.js +7 -0
- package/dist/generic/summarize.types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +8 -4
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Base class for MemberJunction AI Decision providers.
|
|
3
|
+
*
|
|
4
|
+
* This abstract class defines the contract for typed decision models that return
|
|
5
|
+
* enumerated answers with probabilities instead of free text.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/ai
|
|
8
|
+
*/
|
|
9
|
+
import { BaseModel } from './baseModel.js';
|
|
10
|
+
import { DecisionParams, DecisionResult } from './decision.types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for typed decision model implementations.
|
|
13
|
+
* Subclasses wrap provider APIs to produce structured Likelihood, Choice, and Score answers.
|
|
14
|
+
*
|
|
15
|
+
* Implementations should:
|
|
16
|
+
* 1. Register with `@RegisterClass(BaseDecision, 'ProviderName')`
|
|
17
|
+
* 2. Implement the protected `DoDecide()` method
|
|
18
|
+
* 3. Honor `params.CancellationToken`, which the base does not check
|
|
19
|
+
*
|
|
20
|
+
* `Decide()` validates the request before calling `DoDecide()` and the answers after it,
|
|
21
|
+
* so a driver does not repeat those checks.
|
|
22
|
+
*
|
|
23
|
+
* Example:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* @RegisterClass(BaseDecision, 'ExampleDecision')
|
|
26
|
+
* export class ExampleDecision extends BaseDecision {
|
|
27
|
+
* protected async DoDecide(params: DecisionParams): Promise<DecisionResult> {
|
|
28
|
+
* // Call the provider and map its output onto DecisionAnswer shapes
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* const decider = MJGlobal.Instance.ClassFactory.CreateInstance<BaseDecision>(BaseDecision, 'ExampleDecision', apiKey);
|
|
33
|
+
* const result = await decider.Decide(params);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare abstract class BaseDecision extends BaseModel {
|
|
37
|
+
/**
|
|
38
|
+
* Creates an instance of BaseDecision.
|
|
39
|
+
* @param apiKey The API key for the decision service provider.
|
|
40
|
+
*/
|
|
41
|
+
constructor(apiKey: string);
|
|
42
|
+
/**
|
|
43
|
+
* Executes a typed decision request across one or more questions about a given state.
|
|
44
|
+
* This method wraps driver execution with input validation, output verification,
|
|
45
|
+
* execution timing, and structured error handling. It never throws.
|
|
46
|
+
*
|
|
47
|
+
* @param params Decision request parameters including state, questions, and model.
|
|
48
|
+
* @returns A Promise resolving to a DecisionResult.
|
|
49
|
+
*/
|
|
50
|
+
Decide(params: DecisionParams): Promise<DecisionResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Driver-specific implementation of the decision logic.
|
|
53
|
+
* Must be implemented by concrete provider subclasses.
|
|
54
|
+
* Returned probabilities must already be normalised, in range, and keyed correctly.
|
|
55
|
+
*
|
|
56
|
+
* The driver owns cancellation: `Decide()` passes `params.CancellationToken` through
|
|
57
|
+
* unchecked, so the driver should check it before calling the provider and hand it to
|
|
58
|
+
* the provider's HTTP client.
|
|
59
|
+
*
|
|
60
|
+
* @param params Decision parameters to evaluate.
|
|
61
|
+
* @returns A Promise resolving to a DecisionResult.
|
|
62
|
+
*/
|
|
63
|
+
protected abstract DoDecide(params: DecisionParams): Promise<DecisionResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Validates input DecisionParams against the decision contract.
|
|
66
|
+
*
|
|
67
|
+
* @param params Parameters to validate.
|
|
68
|
+
* @returns An array of error descriptions, empty if valid.
|
|
69
|
+
*/
|
|
70
|
+
protected ValidateParams(params: DecisionParams): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Validates that State is a non-empty string once trimmed, or an object with at least one key.
|
|
73
|
+
*/
|
|
74
|
+
private validateState;
|
|
75
|
+
/**
|
|
76
|
+
* Validates the Questions map.
|
|
77
|
+
*/
|
|
78
|
+
private validateQuestions;
|
|
79
|
+
/**
|
|
80
|
+
* Validates a single question definition.
|
|
81
|
+
*/
|
|
82
|
+
private validateSingleQuestion;
|
|
83
|
+
/**
|
|
84
|
+
* Validates a ChoiceQuestion's options (>= 2 options, unique non-empty Values, non-empty Descriptions).
|
|
85
|
+
*/
|
|
86
|
+
private validateChoiceQuestion;
|
|
87
|
+
/**
|
|
88
|
+
* Validates a ScoreQuestion's levels (>= 2 levels, unique non-empty levels).
|
|
89
|
+
*/
|
|
90
|
+
private validateScoreQuestion;
|
|
91
|
+
/**
|
|
92
|
+
* Validates driver output DecisionResult against the requested questions.
|
|
93
|
+
*
|
|
94
|
+
* @param params Original decision request parameters.
|
|
95
|
+
* @param result Result returned by the driver.
|
|
96
|
+
* @returns An array of error descriptions, empty if valid.
|
|
97
|
+
*/
|
|
98
|
+
protected ValidateAnswers(params: DecisionParams, result: DecisionResult): string[];
|
|
99
|
+
/**
|
|
100
|
+
* Validates a single answer against its corresponding question.
|
|
101
|
+
*/
|
|
102
|
+
private validateSingleAnswer;
|
|
103
|
+
/**
|
|
104
|
+
* Validates a LikelihoodAnswer (Probability in [0, 1]).
|
|
105
|
+
*/
|
|
106
|
+
private validateLikelihoodAnswer;
|
|
107
|
+
/**
|
|
108
|
+
* Validates a ChoiceAnswer (Value in options, Confidence in [0, 1], Probabilities match options and sum to 1 +-0.01).
|
|
109
|
+
*/
|
|
110
|
+
private validateChoiceAnswer;
|
|
111
|
+
/**
|
|
112
|
+
* Validates a ScoreAnswer (Value in [0, Levels.length - 1], Confidence in [0, 1], Probabilities match levels and sum to 1 +-0.01).
|
|
113
|
+
*/
|
|
114
|
+
private validateScoreAnswer;
|
|
115
|
+
/**
|
|
116
|
+
* Validates that a probability distribution exactly matches the expected keys,
|
|
117
|
+
* has valid numbers in [0, 1], and sums to 1 within +-0.01 tolerance.
|
|
118
|
+
*/
|
|
119
|
+
private validateProbabilityDistribution;
|
|
120
|
+
/**
|
|
121
|
+
* Checks if a value is a finite number in [0, 1].
|
|
122
|
+
*/
|
|
123
|
+
private isProbabilityInUnitInterval;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=baseDecision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseDecision.d.ts","sourceRoot":"","sources":["../../src/generic/baseDecision.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAIH,cAAc,EAEd,cAAc,EAIjB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,8BAAsB,YAAa,SAAQ,SAAS;IAChD;;;OAGG;gBACS,MAAM,EAAE,MAAM;IAI1B;;;;;;;OAOG;IACU,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAsDpE;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAE5E;;;;;OAKG;IACH,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE;IAW1D;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA2B9B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;;;;;OAMG;IACH,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE;IAyCnF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAQhC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;;OAGG;IACH,OAAO,CAAC,+BAA+B;IAgDvC;;OAEG;IACH,OAAO,CAAC,2BAA2B;CAGtC"}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Base class for MemberJunction AI Decision providers.
|
|
3
|
+
*
|
|
4
|
+
* This abstract class defines the contract for typed decision models that return
|
|
5
|
+
* enumerated answers with probabilities instead of free text.
|
|
6
|
+
*
|
|
7
|
+
* @module @memberjunction/ai
|
|
8
|
+
*/
|
|
9
|
+
import { BaseModel } from './baseModel.js';
|
|
10
|
+
import { ErrorAnalyzer } from './errorAnalyzer.js';
|
|
11
|
+
import { DecisionResult, } from './decision.types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Abstract base class for typed decision model implementations.
|
|
14
|
+
* Subclasses wrap provider APIs to produce structured Likelihood, Choice, and Score answers.
|
|
15
|
+
*
|
|
16
|
+
* Implementations should:
|
|
17
|
+
* 1. Register with `@RegisterClass(BaseDecision, 'ProviderName')`
|
|
18
|
+
* 2. Implement the protected `DoDecide()` method
|
|
19
|
+
* 3. Honor `params.CancellationToken`, which the base does not check
|
|
20
|
+
*
|
|
21
|
+
* `Decide()` validates the request before calling `DoDecide()` and the answers after it,
|
|
22
|
+
* so a driver does not repeat those checks.
|
|
23
|
+
*
|
|
24
|
+
* Example:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* @RegisterClass(BaseDecision, 'ExampleDecision')
|
|
27
|
+
* export class ExampleDecision extends BaseDecision {
|
|
28
|
+
* protected async DoDecide(params: DecisionParams): Promise<DecisionResult> {
|
|
29
|
+
* // Call the provider and map its output onto DecisionAnswer shapes
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* const decider = MJGlobal.Instance.ClassFactory.CreateInstance<BaseDecision>(BaseDecision, 'ExampleDecision', apiKey);
|
|
34
|
+
* const result = await decider.Decide(params);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class BaseDecision extends BaseModel {
|
|
38
|
+
/**
|
|
39
|
+
* Creates an instance of BaseDecision.
|
|
40
|
+
* @param apiKey The API key for the decision service provider.
|
|
41
|
+
*/
|
|
42
|
+
constructor(apiKey) {
|
|
43
|
+
super(apiKey);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Executes a typed decision request across one or more questions about a given state.
|
|
47
|
+
* This method wraps driver execution with input validation, output verification,
|
|
48
|
+
* execution timing, and structured error handling. It never throws.
|
|
49
|
+
*
|
|
50
|
+
* @param params Decision request parameters including state, questions, and model.
|
|
51
|
+
* @returns A Promise resolving to a DecisionResult.
|
|
52
|
+
*/
|
|
53
|
+
async Decide(params) {
|
|
54
|
+
const startTime = new Date();
|
|
55
|
+
try {
|
|
56
|
+
const inputErrors = this.ValidateParams(params);
|
|
57
|
+
if (inputErrors.length > 0) {
|
|
58
|
+
const endTime = new Date();
|
|
59
|
+
const failure = new DecisionResult(false, startTime, endTime);
|
|
60
|
+
failure.errorMessage = inputErrors.join('; ');
|
|
61
|
+
failure.Answers = {};
|
|
62
|
+
return failure;
|
|
63
|
+
}
|
|
64
|
+
const result = await this.DoDecide(params);
|
|
65
|
+
const endTime = new Date();
|
|
66
|
+
if (!result || result.success === false) {
|
|
67
|
+
if (result) {
|
|
68
|
+
// Pass the driver's failure through, but never its answers: whatever it filled
|
|
69
|
+
// in before failing may be partial or malformed.
|
|
70
|
+
result.startTime = startTime;
|
|
71
|
+
result.endTime = endTime;
|
|
72
|
+
result.Answers = {};
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
const failure = new DecisionResult(false, startTime, endTime);
|
|
76
|
+
failure.errorMessage = 'Driver returned null or undefined result';
|
|
77
|
+
failure.Answers = {};
|
|
78
|
+
return failure;
|
|
79
|
+
}
|
|
80
|
+
const outputErrors = this.ValidateAnswers(params, result);
|
|
81
|
+
if (outputErrors.length > 0) {
|
|
82
|
+
const failure = new DecisionResult(false, startTime, endTime);
|
|
83
|
+
failure.errorMessage = outputErrors.join('; ');
|
|
84
|
+
failure.Answers = {};
|
|
85
|
+
failure.Usage = result.Usage;
|
|
86
|
+
failure.ResolvedModel = result.ResolvedModel;
|
|
87
|
+
return failure;
|
|
88
|
+
}
|
|
89
|
+
result.startTime = startTime;
|
|
90
|
+
result.endTime = endTime;
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const endTime = new Date();
|
|
95
|
+
const failure = new DecisionResult(false, startTime, endTime);
|
|
96
|
+
failure.errorMessage = error instanceof Error ? error.message : String(error);
|
|
97
|
+
failure.exception = error;
|
|
98
|
+
failure.errorInfo = ErrorAnalyzer.AnalyzeError(error, this.constructor.name);
|
|
99
|
+
failure.Answers = {};
|
|
100
|
+
return failure;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validates input DecisionParams against the decision contract.
|
|
105
|
+
*
|
|
106
|
+
* @param params Parameters to validate.
|
|
107
|
+
* @returns An array of error descriptions, empty if valid.
|
|
108
|
+
*/
|
|
109
|
+
ValidateParams(params) {
|
|
110
|
+
const errors = [];
|
|
111
|
+
if (!params || typeof params !== 'object') {
|
|
112
|
+
return ['DecisionParams must be an object'];
|
|
113
|
+
}
|
|
114
|
+
errors.push(...this.validateState(params.State));
|
|
115
|
+
errors.push(...this.validateQuestions(params.Questions));
|
|
116
|
+
return errors;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validates that State is a non-empty string once trimmed, or an object with at least one key.
|
|
120
|
+
*/
|
|
121
|
+
validateState(state) {
|
|
122
|
+
if (typeof state === 'string') {
|
|
123
|
+
if (state.trim().length === 0) {
|
|
124
|
+
return ['State must be a non-empty string once trimmed, or an object with at least one key'];
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
if (typeof state === 'object' && state !== null && !Array.isArray(state)) {
|
|
129
|
+
if (Object.keys(state).length === 0) {
|
|
130
|
+
return ['State must be a non-empty string once trimmed, or an object with at least one key'];
|
|
131
|
+
}
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
return ['State must be a non-empty string once trimmed, or an object with at least one key'];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Validates the Questions map.
|
|
138
|
+
*/
|
|
139
|
+
validateQuestions(questions) {
|
|
140
|
+
if (!questions || typeof questions !== 'object' || Array.isArray(questions)) {
|
|
141
|
+
return ['Questions must have at least one entry'];
|
|
142
|
+
}
|
|
143
|
+
const keys = Object.keys(questions);
|
|
144
|
+
if (keys.length === 0) {
|
|
145
|
+
return ['Questions must have at least one entry'];
|
|
146
|
+
}
|
|
147
|
+
const errors = [];
|
|
148
|
+
const record = questions;
|
|
149
|
+
for (const key of keys) {
|
|
150
|
+
if (key.trim().length === 0) {
|
|
151
|
+
errors.push('Question key must be a non-empty string once trimmed');
|
|
152
|
+
}
|
|
153
|
+
const q = record[key];
|
|
154
|
+
errors.push(...this.validateSingleQuestion(key, q));
|
|
155
|
+
}
|
|
156
|
+
return errors;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Validates a single question definition.
|
|
160
|
+
*/
|
|
161
|
+
validateSingleQuestion(key, q) {
|
|
162
|
+
if (!q || typeof q !== 'object') {
|
|
163
|
+
return [`Question '${key}': Question definition must be an object`];
|
|
164
|
+
}
|
|
165
|
+
const question = q;
|
|
166
|
+
const errors = [];
|
|
167
|
+
if (typeof question.Instructions !== 'string' || question.Instructions.trim().length === 0) {
|
|
168
|
+
errors.push(`Question '${key}': Instructions must be a non-empty string once trimmed`);
|
|
169
|
+
}
|
|
170
|
+
switch (question.Kind) {
|
|
171
|
+
case 'Likelihood':
|
|
172
|
+
break;
|
|
173
|
+
case 'Choice':
|
|
174
|
+
errors.push(...this.validateChoiceQuestion(key, q));
|
|
175
|
+
break;
|
|
176
|
+
case 'Score':
|
|
177
|
+
errors.push(...this.validateScoreQuestion(key, q));
|
|
178
|
+
break;
|
|
179
|
+
default:
|
|
180
|
+
errors.push(`Question '${key}': Unknown question Kind '${String(question.Kind)}'`);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
return errors;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Validates a ChoiceQuestion's options (>= 2 options, unique non-empty Values, non-empty Descriptions).
|
|
187
|
+
*/
|
|
188
|
+
validateChoiceQuestion(key, q) {
|
|
189
|
+
const errors = [];
|
|
190
|
+
if (!Array.isArray(q.Options) || q.Options.length < 2) {
|
|
191
|
+
errors.push(`Question '${key}': Choice question must have at least 2 options`);
|
|
192
|
+
return errors;
|
|
193
|
+
}
|
|
194
|
+
const seenValues = new Set();
|
|
195
|
+
for (const opt of q.Options) {
|
|
196
|
+
if (!opt || typeof opt !== 'object') {
|
|
197
|
+
errors.push(`Question '${key}': Choice option must be an object`);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (typeof opt.Value !== 'string' || opt.Value.trim().length === 0) {
|
|
201
|
+
errors.push(`Question '${key}': Choice option Value must be a non-empty string`);
|
|
202
|
+
}
|
|
203
|
+
else if (seenValues.has(opt.Value)) {
|
|
204
|
+
errors.push(`Question '${key}': Duplicate Choice option Value '${opt.Value}'`);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
seenValues.add(opt.Value);
|
|
208
|
+
}
|
|
209
|
+
if (typeof opt.Description !== 'string' || opt.Description.trim().length === 0) {
|
|
210
|
+
errors.push(`Question '${key}': Choice option Description must be a non-empty string`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return errors;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Validates a ScoreQuestion's levels (>= 2 levels, unique non-empty levels).
|
|
217
|
+
*/
|
|
218
|
+
validateScoreQuestion(key, q) {
|
|
219
|
+
const errors = [];
|
|
220
|
+
if (!Array.isArray(q.Levels) || q.Levels.length < 2) {
|
|
221
|
+
errors.push(`Question '${key}': Score question must have at least 2 levels`);
|
|
222
|
+
return errors;
|
|
223
|
+
}
|
|
224
|
+
const seenLevels = new Set();
|
|
225
|
+
for (const level of q.Levels) {
|
|
226
|
+
if (typeof level !== 'string' || level.trim().length === 0) {
|
|
227
|
+
errors.push(`Question '${key}': Score level must be a non-empty string`);
|
|
228
|
+
}
|
|
229
|
+
else if (seenLevels.has(level)) {
|
|
230
|
+
errors.push(`Question '${key}': Duplicate Score level '${level}'`);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
seenLevels.add(level);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return errors;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Validates driver output DecisionResult against the requested questions.
|
|
240
|
+
*
|
|
241
|
+
* @param params Original decision request parameters.
|
|
242
|
+
* @param result Result returned by the driver.
|
|
243
|
+
* @returns An array of error descriptions, empty if valid.
|
|
244
|
+
*/
|
|
245
|
+
ValidateAnswers(params, result) {
|
|
246
|
+
const errors = [];
|
|
247
|
+
if (!result || !result.Answers || typeof result.Answers !== 'object' || Array.isArray(result.Answers)) {
|
|
248
|
+
return ['Result Answers must be an object'];
|
|
249
|
+
}
|
|
250
|
+
if (!params || !params.Questions || typeof params.Questions !== 'object') {
|
|
251
|
+
return ['Params Questions must be an object'];
|
|
252
|
+
}
|
|
253
|
+
const questionKeys = Object.keys(params.Questions);
|
|
254
|
+
const answerKeys = Object.keys(result.Answers);
|
|
255
|
+
// Key checks use Object.hasOwn, not `in`: `in` also sees inherited Object.prototype
|
|
256
|
+
// names, so a key such as 'toString' or 'constructor' would count as present.
|
|
257
|
+
// Every question key has exactly one answer
|
|
258
|
+
for (const qKey of questionKeys) {
|
|
259
|
+
if (!Object.hasOwn(result.Answers, qKey) || result.Answers[qKey] === undefined) {
|
|
260
|
+
errors.push(`Question '${qKey}': Missing answer`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// No answers for keys that were not asked
|
|
264
|
+
for (const aKey of answerKeys) {
|
|
265
|
+
if (!Object.hasOwn(params.Questions, aKey)) {
|
|
266
|
+
errors.push(`Answer provided for unexpected question '${aKey}'`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Validate each answered question
|
|
270
|
+
for (const qKey of questionKeys) {
|
|
271
|
+
if (Object.hasOwn(result.Answers, qKey) && result.Answers[qKey] !== undefined) {
|
|
272
|
+
const question = params.Questions[qKey];
|
|
273
|
+
const answer = result.Answers[qKey];
|
|
274
|
+
errors.push(...this.validateSingleAnswer(qKey, question, answer));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return errors;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Validates a single answer against its corresponding question.
|
|
281
|
+
*/
|
|
282
|
+
validateSingleAnswer(key, question, answer) {
|
|
283
|
+
if (!answer || typeof answer !== 'object') {
|
|
284
|
+
return [`Question '${key}': Answer must be an object`];
|
|
285
|
+
}
|
|
286
|
+
// Narrowing on both discriminants types each branch without a cast. Question kinds were
|
|
287
|
+
// checked on input, so anything that falls through is a kind mismatch.
|
|
288
|
+
if (question.Kind === 'Likelihood' && answer.Kind === 'Likelihood') {
|
|
289
|
+
return this.validateLikelihoodAnswer(key, answer);
|
|
290
|
+
}
|
|
291
|
+
if (question.Kind === 'Choice' && answer.Kind === 'Choice') {
|
|
292
|
+
return this.validateChoiceAnswer(key, question, answer);
|
|
293
|
+
}
|
|
294
|
+
if (question.Kind === 'Score' && answer.Kind === 'Score') {
|
|
295
|
+
return this.validateScoreAnswer(key, question, answer);
|
|
296
|
+
}
|
|
297
|
+
return [`Question '${key}': Answer Kind '${answer.Kind}' does not match question Kind '${question.Kind}'`];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Validates a LikelihoodAnswer (Probability in [0, 1]).
|
|
301
|
+
*/
|
|
302
|
+
validateLikelihoodAnswer(key, answer) {
|
|
303
|
+
const errors = [];
|
|
304
|
+
if (!this.isProbabilityInUnitInterval(answer.Probability)) {
|
|
305
|
+
errors.push(`Question '${key}': Likelihood Probability must be a finite number in [0, 1], got ${answer.Probability}`);
|
|
306
|
+
}
|
|
307
|
+
return errors;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Validates a ChoiceAnswer (Value in options, Confidence in [0, 1], Probabilities match options and sum to 1 +-0.01).
|
|
311
|
+
*/
|
|
312
|
+
validateChoiceAnswer(key, question, answer) {
|
|
313
|
+
const errors = [];
|
|
314
|
+
if (!this.isProbabilityInUnitInterval(answer.Confidence)) {
|
|
315
|
+
errors.push(`Question '${key}': Choice Confidence must be a finite number in [0, 1], got ${answer.Confidence}`);
|
|
316
|
+
}
|
|
317
|
+
const validOptionValues = new Set(question.Options.map(o => o.Value));
|
|
318
|
+
if (typeof answer.Value !== 'string' || !validOptionValues.has(answer.Value)) {
|
|
319
|
+
errors.push(`Question '${key}': Choice value '${answer.Value}' is not one of the options`);
|
|
320
|
+
}
|
|
321
|
+
errors.push(...this.validateProbabilityDistribution(key, 'option', question.Options.map(o => o.Value), answer.Probabilities));
|
|
322
|
+
return errors;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Validates a ScoreAnswer (Value in [0, Levels.length - 1], Confidence in [0, 1], Probabilities match levels and sum to 1 +-0.01).
|
|
326
|
+
*/
|
|
327
|
+
validateScoreAnswer(key, question, answer) {
|
|
328
|
+
const errors = [];
|
|
329
|
+
if (!this.isProbabilityInUnitInterval(answer.Confidence)) {
|
|
330
|
+
errors.push(`Question '${key}': Score Confidence must be a finite number in [0, 1], got ${answer.Confidence}`);
|
|
331
|
+
}
|
|
332
|
+
const maxLevel = question.Levels.length - 1;
|
|
333
|
+
if (typeof answer.Value !== 'number' || !Number.isFinite(answer.Value) || answer.Value < 0 || answer.Value > maxLevel) {
|
|
334
|
+
errors.push(`Question '${key}': Score value ${answer.Value} must be a finite number in [0, ${maxLevel}]`);
|
|
335
|
+
}
|
|
336
|
+
errors.push(...this.validateProbabilityDistribution(key, 'level', question.Levels, answer.Probabilities));
|
|
337
|
+
return errors;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Validates that a probability distribution exactly matches the expected keys,
|
|
341
|
+
* has valid numbers in [0, 1], and sums to 1 within +-0.01 tolerance.
|
|
342
|
+
*/
|
|
343
|
+
validateProbabilityDistribution(key, entityName, expectedKeys, probabilities) {
|
|
344
|
+
const errors = [];
|
|
345
|
+
if (!probabilities || typeof probabilities !== 'object' || Array.isArray(probabilities)) {
|
|
346
|
+
return [`Question '${key}': Probabilities must be an object`];
|
|
347
|
+
}
|
|
348
|
+
const expectedSet = new Set(expectedKeys);
|
|
349
|
+
const actualKeys = Object.keys(probabilities);
|
|
350
|
+
for (const expectedKey of expectedKeys) {
|
|
351
|
+
if (!Object.hasOwn(probabilities, expectedKey)) {
|
|
352
|
+
errors.push(`Question '${key}': Probabilities missing key for ${entityName} '${expectedKey}'`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
for (const actualKey of actualKeys) {
|
|
356
|
+
if (!expectedSet.has(actualKey)) {
|
|
357
|
+
errors.push(`Question '${key}': Probabilities contains unexpected key '${actualKey}'`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
let sum = 0;
|
|
361
|
+
let allValidNumbers = true;
|
|
362
|
+
for (const actualKey of actualKeys) {
|
|
363
|
+
const prob = probabilities[actualKey];
|
|
364
|
+
if (!this.isProbabilityInUnitInterval(prob)) {
|
|
365
|
+
errors.push(`Question '${key}': Probability for ${entityName} '${actualKey}' must be a finite number in [0, 1], got ${prob}`);
|
|
366
|
+
allValidNumbers = false;
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
sum += prob;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (allValidNumbers && actualKeys.length > 0) {
|
|
373
|
+
if (Math.abs(sum - 1) > 0.01 + 1e-9) {
|
|
374
|
+
const formattedSum = Number(sum.toFixed(6));
|
|
375
|
+
errors.push(`Question '${key}': Probabilities sum to ${formattedSum}, which is outside tolerance [0.99, 1.01]`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return errors;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Checks if a value is a finite number in [0, 1].
|
|
382
|
+
*/
|
|
383
|
+
isProbabilityInUnitInterval(val) {
|
|
384
|
+
return typeof val === 'number' && Number.isFinite(val) && val >= 0 && val <= 1;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=baseDecision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseDecision.js","sourceRoot":"","sources":["../../src/generic/baseDecision.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ export class GeneratedImage {
|
|
|
8
8
|
/**
|
|
9
9
|
* The image format/encoding
|
|
10
10
|
*/
|
|
11
|
-
this.format = 'png';
|
|
11
|
+
this.format = 'png'; // case-violation-ok-legacy-back-compat: object literals are assigned to this class, so an accessor stub changes what they must supply
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
@@ -20,7 +20,7 @@ export class ImageGenerationResult extends BaseResult {
|
|
|
20
20
|
/**
|
|
21
21
|
* Array of generated images. May contain multiple images if n > 1 was requested.
|
|
22
22
|
*/
|
|
23
|
-
this.images = [];
|
|
23
|
+
this.images = []; // case-violation-ok-legacy-back-compat: object literals are assigned to this class, so an accessor stub changes what they must supply
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
@@ -32,19 +32,19 @@ export class ImageGenerationParams {
|
|
|
32
32
|
* Number of images to generate. Default is 1.
|
|
33
33
|
* Some providers have limits on the maximum number.
|
|
34
34
|
*/
|
|
35
|
-
this.n = 1;
|
|
35
|
+
this.n = 1; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
36
36
|
/**
|
|
37
37
|
* Size of the generated image(s)
|
|
38
38
|
*/
|
|
39
|
-
this.size = '1024x1024';
|
|
39
|
+
this.size = '1024x1024'; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
40
40
|
/**
|
|
41
41
|
* Quality level for the generated image
|
|
42
42
|
*/
|
|
43
|
-
this.quality = 'standard';
|
|
43
|
+
this.quality = 'standard'; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
44
44
|
/**
|
|
45
45
|
* How the generated image should be returned
|
|
46
46
|
*/
|
|
47
|
-
this.outputFormat = 'b64_json';
|
|
47
|
+
this.outputFormat = 'b64_json'; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
@@ -55,11 +55,11 @@ export class ImageEditParams {
|
|
|
55
55
|
/**
|
|
56
56
|
* Number of edited images to generate
|
|
57
57
|
*/
|
|
58
|
-
this.n = 1;
|
|
58
|
+
this.n = 1; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
59
59
|
/**
|
|
60
60
|
* How the result should be returned
|
|
61
61
|
*/
|
|
62
|
-
this.outputFormat = 'b64_json';
|
|
62
|
+
this.outputFormat = 'b64_json'; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
@@ -70,11 +70,11 @@ export class ImageVariationParams {
|
|
|
70
70
|
/**
|
|
71
71
|
* Number of variations to generate
|
|
72
72
|
*/
|
|
73
|
-
this.n = 1;
|
|
73
|
+
this.n = 1; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
74
74
|
/**
|
|
75
75
|
* How the result should be returned
|
|
76
76
|
*/
|
|
77
|
-
this.outputFormat = 'b64_json';
|
|
77
|
+
this.outputFormat = 'b64_json'; // case-violation-ok-legacy-back-compat: an accessor cannot be optional, so a stub would turn this into a required member
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseImage.js","sourceRoot":"","sources":["../../src/generic/baseImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAEhE;;;GAGG;AACH,MAAM,OAAO,cAAc;IAA3B;QAmBI;;WAEG;QACH,WAAM,GAA4C,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"baseImage.js","sourceRoot":"","sources":["../../src/generic/baseImage.ts"],"names":[],"mappings":"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"}
|