elasticsearch-mcp-vsee-stage 0.5.13
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/LICENSE +21 -0
- package/README.md +304 -0
- package/build/config.d.ts +76 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +63 -0
- package/build/config.js.map +1 -0
- package/build/elasticsearch/client.d.ts +26 -0
- package/build/elasticsearch/client.d.ts.map +1 -0
- package/build/elasticsearch/client.js +131 -0
- package/build/elasticsearch/client.js.map +1 -0
- package/build/errors/handlers.d.ts +44 -0
- package/build/errors/handlers.d.ts.map +1 -0
- package/build/errors/handlers.js +231 -0
- package/build/errors/handlers.js.map +1 -0
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +28 -0
- package/build/index.js.map +1 -0
- package/build/logger.d.ts +31 -0
- package/build/logger.d.ts.map +1 -0
- package/build/logger.js +81 -0
- package/build/logger.js.map +1 -0
- package/build/server.d.ts +23 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +571 -0
- package/build/server.js.map +1 -0
- package/build/tools/find-entities-by-metric.d.ts +51 -0
- package/build/tools/find-entities-by-metric.d.ts.map +1 -0
- package/build/tools/find-entities-by-metric.js +375 -0
- package/build/tools/find-entities-by-metric.js.map +1 -0
- package/build/tools/get-index-fields.d.ts +26 -0
- package/build/tools/get-index-fields.d.ts.map +1 -0
- package/build/tools/get-index-fields.js +94 -0
- package/build/tools/get-index-fields.js.map +1 -0
- package/build/tools/get-platform-breakdown.d.ts +42 -0
- package/build/tools/get-platform-breakdown.d.ts.map +1 -0
- package/build/tools/get-platform-breakdown.js +305 -0
- package/build/tools/get-platform-breakdown.js.map +1 -0
- package/build/tools/get-rating-distribution.d.ts +48 -0
- package/build/tools/get-rating-distribution.d.ts.map +1 -0
- package/build/tools/get-rating-distribution.js +283 -0
- package/build/tools/get-rating-distribution.js.map +1 -0
- package/build/tools/get-subscription-breakdown.d.ts +34 -0
- package/build/tools/get-subscription-breakdown.d.ts.map +1 -0
- package/build/tools/get-subscription-breakdown.js +179 -0
- package/build/tools/get-subscription-breakdown.js.map +1 -0
- package/build/tools/get-usage-leaderboard.d.ts +38 -0
- package/build/tools/get-usage-leaderboard.d.ts.map +1 -0
- package/build/tools/get-usage-leaderboard.js +177 -0
- package/build/tools/get-usage-leaderboard.js.map +1 -0
- package/build/tools/get-usage-profile.d.ts +52 -0
- package/build/tools/get-usage-profile.d.ts.map +1 -0
- package/build/tools/get-usage-profile.js +273 -0
- package/build/tools/get-usage-profile.js.map +1 -0
- package/build/tools/get-visit-trends.d.ts +37 -0
- package/build/tools/get-visit-trends.d.ts.map +1 -0
- package/build/tools/get-visit-trends.js +289 -0
- package/build/tools/get-visit-trends.js.map +1 -0
- package/build/tools/index.d.ts +19 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +22 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/top-change.d.ts +34 -0
- package/build/tools/top-change.d.ts.map +1 -0
- package/build/tools/top-change.js +262 -0
- package/build/tools/top-change.js.map +1 -0
- package/build/utils/aggregation-limits.d.ts +23 -0
- package/build/utils/aggregation-limits.d.ts.map +1 -0
- package/build/utils/aggregation-limits.js +32 -0
- package/build/utils/aggregation-limits.js.map +1 -0
- package/build/utils/date-math.d.ts +31 -0
- package/build/utils/date-math.d.ts.map +1 -0
- package/build/utils/date-math.js +116 -0
- package/build/utils/date-math.js.map +1 -0
- package/build/utils/field-constants.d.ts +23 -0
- package/build/utils/field-constants.d.ts.map +1 -0
- package/build/utils/field-constants.js +26 -0
- package/build/utils/field-constants.js.map +1 -0
- package/build/validation/schemas.d.ts +243 -0
- package/build/validation/schemas.d.ts.map +1 -0
- package/build/validation/schemas.js +151 -0
- package/build/validation/schemas.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetPlatformBreakdownTool = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const handlers_js_1 = require("../errors/handlers.js");
|
|
6
|
+
//import { capTimePeriod } from '../utils/date-math.js';
|
|
7
|
+
const aggregation_limits_js_1 = require("../utils/aggregation-limits.js");
|
|
8
|
+
const field_constants_js_1 = require("../utils/field-constants.js");
|
|
9
|
+
const GetPlatformBreakdownArgsSchema = zod_1.z.object({
|
|
10
|
+
role: zod_1.z.enum(['provider', 'patient']).describe('Role: "provider" for provider platforms/versions, "patient" for patient platforms/versions'),
|
|
11
|
+
breakdownType: zod_1.z.enum(['platform', 'version']).describe('Breakdown type: "platform" for platform breakdown (Web/iOS/Android), "version" for platform version breakdown'),
|
|
12
|
+
topN: zod_1.z.number().int().min(1).max(100).optional().default(10).describe('Number of top items to return (default: 10, max: 100)'),
|
|
13
|
+
startDate: zod_1.z.string().optional().describe('Start date in ISO format (YYYY-MM-DD) or date math (e.g., "now-30d", "now-1y"). Defaults to "now-30d"'),
|
|
14
|
+
endDate: zod_1.z.string().optional().describe('End date in ISO format (YYYY-MM-DD) or date math (e.g., "now"). Defaults to "now"'),
|
|
15
|
+
account: zod_1.z.string().optional().describe('Optional account name to filter data to'),
|
|
16
|
+
group: zod_1.z.string().optional().describe('Optional group name to filter data to'),
|
|
17
|
+
}).strict();
|
|
18
|
+
class GetPlatformBreakdownTool {
|
|
19
|
+
elasticsearch;
|
|
20
|
+
logger;
|
|
21
|
+
constructor(elasticsearch, logger) {
|
|
22
|
+
this.elasticsearch = elasticsearch;
|
|
23
|
+
this.logger = logger.child({ tool: 'get-platform-breakdown' });
|
|
24
|
+
}
|
|
25
|
+
async execute(args) {
|
|
26
|
+
try {
|
|
27
|
+
const validatedArgs = GetPlatformBreakdownArgsSchema.parse(args);
|
|
28
|
+
const topN = Math.min(validatedArgs.topN || 10, 50);
|
|
29
|
+
let startDate = validatedArgs.startDate || 'now-14d';
|
|
30
|
+
let endDate = validatedArgs.endDate || 'now';
|
|
31
|
+
// Platform breakdowns use terms aggregation on high-cardinality fields (especially patient platforms).
|
|
32
|
+
// Cap time period to prevent data limit errors.
|
|
33
|
+
//const { startDate: adjustedStartDate, endDate: adjustedEndDate } = capTimePeriod(
|
|
34
|
+
// startDate,
|
|
35
|
+
// endDate,
|
|
36
|
+
// 30, // Max 30 days for platform breakdowns
|
|
37
|
+
// this.logger
|
|
38
|
+
//);
|
|
39
|
+
//startDate = adjustedStartDate;
|
|
40
|
+
//endDate = adjustedEndDate;
|
|
41
|
+
this.logger.info('Getting platform breakdown', {
|
|
42
|
+
role: validatedArgs.role,
|
|
43
|
+
breakdownType: validatedArgs.breakdownType,
|
|
44
|
+
topN,
|
|
45
|
+
originalTopN: validatedArgs.topN,
|
|
46
|
+
startDate,
|
|
47
|
+
endDate,
|
|
48
|
+
account: validatedArgs.account,
|
|
49
|
+
group: validatedArgs.group,
|
|
50
|
+
});
|
|
51
|
+
const client = this.elasticsearch.getClient();
|
|
52
|
+
const index = field_constants_js_1.FIELD_CONSTANTS.index;
|
|
53
|
+
const timeField = field_constants_js_1.FIELD_CONSTANTS.timeField;
|
|
54
|
+
const testVisitField = field_constants_js_1.FIELD_CONSTANTS.testVisitField;
|
|
55
|
+
const subscriptionField = field_constants_js_1.FIELD_CONSTANTS.subscriptionField;
|
|
56
|
+
const accountField = field_constants_js_1.FIELD_CONSTANTS.accountField;
|
|
57
|
+
const groupField = field_constants_js_1.FIELD_CONSTANTS.groupField;
|
|
58
|
+
const providerField = field_constants_js_1.FIELD_CONSTANTS.providerField;
|
|
59
|
+
const patientField = field_constants_js_1.FIELD_CONSTANTS.patientField;
|
|
60
|
+
const callDurationField = field_constants_js_1.FIELD_CONSTANTS.callDurationField;
|
|
61
|
+
const providerRatingField = field_constants_js_1.FIELD_CONSTANTS.providerRatingField;
|
|
62
|
+
const patientRatingField = field_constants_js_1.FIELD_CONSTANTS.patientRatingField;
|
|
63
|
+
const meetingBasedField = field_constants_js_1.FIELD_CONSTANTS.meetingBasedField;
|
|
64
|
+
let aggregationField;
|
|
65
|
+
if (validatedArgs.role === 'provider') {
|
|
66
|
+
aggregationField = validatedArgs.breakdownType === 'version'
|
|
67
|
+
? 'provider0_platform_version.keyword'
|
|
68
|
+
: 'provider0_platform.keyword';
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
aggregationField = validatedArgs.breakdownType === 'version'
|
|
72
|
+
? 'patient0_platform_version.keyword'
|
|
73
|
+
: 'patient0_platform.keyword';
|
|
74
|
+
}
|
|
75
|
+
const filters = [
|
|
76
|
+
{
|
|
77
|
+
range: {
|
|
78
|
+
[timeField]: {
|
|
79
|
+
gte: startDate,
|
|
80
|
+
lt: endDate,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
term: {
|
|
86
|
+
[testVisitField]: 'No',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
bool: {
|
|
91
|
+
should: [
|
|
92
|
+
{ exists: { field: callDurationField } },
|
|
93
|
+
{ term: { [meetingBasedField]: false } },
|
|
94
|
+
],
|
|
95
|
+
minimum_should_match: 1,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
if (validatedArgs.account) {
|
|
100
|
+
filters.push({
|
|
101
|
+
term: {
|
|
102
|
+
[accountField]: validatedArgs.account,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (validatedArgs.group) {
|
|
107
|
+
filters.push({
|
|
108
|
+
term: {
|
|
109
|
+
[groupField]: validatedArgs.group,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const query = {
|
|
114
|
+
index,
|
|
115
|
+
size: 0,
|
|
116
|
+
body: {
|
|
117
|
+
track_total_hits: false,
|
|
118
|
+
query: {
|
|
119
|
+
bool: {
|
|
120
|
+
filter: filters,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
aggs: {
|
|
124
|
+
by_item: {
|
|
125
|
+
terms: {
|
|
126
|
+
field: aggregationField,
|
|
127
|
+
size: (0, aggregation_limits_js_1.calculateTermsSize)(topN || 10, 2, aggregation_limits_js_1.AGGREGATION_LIMITS.LARGE),
|
|
128
|
+
order: { _count: 'desc' },
|
|
129
|
+
},
|
|
130
|
+
aggs: {
|
|
131
|
+
count_records: {
|
|
132
|
+
value_count: { field: timeField },
|
|
133
|
+
},
|
|
134
|
+
unique_accounts: {
|
|
135
|
+
cardinality: { field: accountField },
|
|
136
|
+
},
|
|
137
|
+
unique_providers: {
|
|
138
|
+
cardinality: { field: providerField },
|
|
139
|
+
},
|
|
140
|
+
unique_patients: {
|
|
141
|
+
cardinality: { field: patientField },
|
|
142
|
+
},
|
|
143
|
+
avg_call_duration: {
|
|
144
|
+
avg: { field: callDurationField },
|
|
145
|
+
},
|
|
146
|
+
provider_rating_count: {
|
|
147
|
+
value_count: { field: providerRatingField },
|
|
148
|
+
},
|
|
149
|
+
avg_provider_rating: {
|
|
150
|
+
avg: { field: providerRatingField },
|
|
151
|
+
},
|
|
152
|
+
patient_rating_count: {
|
|
153
|
+
value_count: { field: patientRatingField },
|
|
154
|
+
},
|
|
155
|
+
avg_patient_rating: {
|
|
156
|
+
avg: { field: patientRatingField },
|
|
157
|
+
},
|
|
158
|
+
subscription_distribution: {
|
|
159
|
+
terms: {
|
|
160
|
+
field: subscriptionField,
|
|
161
|
+
size: aggregation_limits_js_1.AGGREGATION_LIMITS.SMALL * 2, // 20 for subscription distribution
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
this.logger.debug('Executing query', { query: JSON.stringify(query, null, 2) });
|
|
170
|
+
const response = await client.search(query);
|
|
171
|
+
const aggs = response.aggregations;
|
|
172
|
+
const itemBuckets = aggs?.by_item?.buckets || [];
|
|
173
|
+
const topItems = [];
|
|
174
|
+
let otherRecords = 0;
|
|
175
|
+
let otherAccounts = 0;
|
|
176
|
+
let otherProviders = 0;
|
|
177
|
+
let otherPatients = 0;
|
|
178
|
+
let otherCallDurationSum = 0;
|
|
179
|
+
let otherCallDurationCount = 0;
|
|
180
|
+
let otherProviderRatingSum = 0;
|
|
181
|
+
let otherProviderRatingCount = 0;
|
|
182
|
+
let otherPatientRatingSum = 0;
|
|
183
|
+
let otherPatientRatingCount = 0;
|
|
184
|
+
const otherSubscriptionMap = new Map();
|
|
185
|
+
for (let i = 0; i < itemBuckets.length; i++) {
|
|
186
|
+
const bucket = itemBuckets[i];
|
|
187
|
+
const item = bucket.key;
|
|
188
|
+
const countRecords = bucket.count_records?.value || bucket.doc_count || 0;
|
|
189
|
+
const uniqueAccounts = bucket.unique_accounts?.value || 0;
|
|
190
|
+
const uniqueProviders = bucket.unique_providers?.value || 0;
|
|
191
|
+
const uniquePatients = bucket.unique_patients?.value || 0;
|
|
192
|
+
const avgCallDuration = bucket.avg_call_duration?.value || null;
|
|
193
|
+
const providerRatingCount = bucket.provider_rating_count?.value || 0;
|
|
194
|
+
const avgProviderRating = bucket.avg_provider_rating?.value || null;
|
|
195
|
+
const patientRatingCount = bucket.patient_rating_count?.value || 0;
|
|
196
|
+
const avgPatientRating = bucket.avg_patient_rating?.value || null;
|
|
197
|
+
const subscriptionDist = [];
|
|
198
|
+
const subscriptionBuckets = bucket.subscription_distribution?.buckets || [];
|
|
199
|
+
for (const subBucket of subscriptionBuckets) {
|
|
200
|
+
subscriptionDist.push({
|
|
201
|
+
subscription: subBucket.key,
|
|
202
|
+
count: subBucket.doc_count || 0,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const itemMetrics = {
|
|
206
|
+
platform: item,
|
|
207
|
+
count_records: countRecords,
|
|
208
|
+
unique_accounts: uniqueAccounts,
|
|
209
|
+
unique_providers: uniqueProviders,
|
|
210
|
+
unique_patients: uniquePatients,
|
|
211
|
+
avg_call_duration: avgCallDuration ? Math.round(avgCallDuration * 100) / 100 : null,
|
|
212
|
+
provider_rating_count: providerRatingCount,
|
|
213
|
+
avg_provider_rating: avgProviderRating ? Math.round(avgProviderRating * 100) / 100 : null,
|
|
214
|
+
patient_rating_count: patientRatingCount,
|
|
215
|
+
avg_patient_rating: avgPatientRating ? Math.round(avgPatientRating * 100) / 100 : null,
|
|
216
|
+
subscription_distribution: subscriptionDist,
|
|
217
|
+
};
|
|
218
|
+
if (i < topN) {
|
|
219
|
+
topItems.push(itemMetrics);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
otherRecords += countRecords;
|
|
223
|
+
otherAccounts += uniqueAccounts;
|
|
224
|
+
otherProviders += uniqueProviders;
|
|
225
|
+
otherPatients += uniquePatients;
|
|
226
|
+
if (avgCallDuration !== null) {
|
|
227
|
+
otherCallDurationSum += avgCallDuration * countRecords;
|
|
228
|
+
otherCallDurationCount += countRecords;
|
|
229
|
+
}
|
|
230
|
+
if (avgProviderRating !== null) {
|
|
231
|
+
otherProviderRatingSum += avgProviderRating * providerRatingCount;
|
|
232
|
+
otherProviderRatingCount += providerRatingCount;
|
|
233
|
+
}
|
|
234
|
+
if (avgPatientRating !== null) {
|
|
235
|
+
otherPatientRatingSum += avgPatientRating * patientRatingCount;
|
|
236
|
+
otherPatientRatingCount += patientRatingCount;
|
|
237
|
+
}
|
|
238
|
+
for (const sub of subscriptionDist) {
|
|
239
|
+
const current = otherSubscriptionMap.get(sub.subscription) || 0;
|
|
240
|
+
otherSubscriptionMap.set(sub.subscription, current + sub.count);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
let otherItems = null;
|
|
245
|
+
if (itemBuckets.length > topN) {
|
|
246
|
+
const otherSubscriptionDist = [];
|
|
247
|
+
for (const [subscription, count] of otherSubscriptionMap.entries()) {
|
|
248
|
+
otherSubscriptionDist.push({ subscription, count });
|
|
249
|
+
}
|
|
250
|
+
otherItems = {
|
|
251
|
+
platform: `Other (${itemBuckets.length - topN} ${validatedArgs.breakdownType === 'version' ? 'versions' : 'platforms'})`,
|
|
252
|
+
count_records: otherRecords,
|
|
253
|
+
unique_accounts: otherAccounts,
|
|
254
|
+
unique_providers: otherProviders,
|
|
255
|
+
unique_patients: otherPatients,
|
|
256
|
+
avg_call_duration: otherCallDurationCount > 0
|
|
257
|
+
? Math.round((otherCallDurationSum / otherCallDurationCount) * 100) / 100
|
|
258
|
+
: null,
|
|
259
|
+
provider_rating_count: otherProviderRatingCount,
|
|
260
|
+
avg_provider_rating: otherProviderRatingCount > 0
|
|
261
|
+
? Math.round((otherProviderRatingSum / otherProviderRatingCount) * 100) / 100
|
|
262
|
+
: null,
|
|
263
|
+
patient_rating_count: otherPatientRatingCount,
|
|
264
|
+
avg_patient_rating: otherPatientRatingCount > 0
|
|
265
|
+
? Math.round((otherPatientRatingSum / otherPatientRatingCount) * 100) / 100
|
|
266
|
+
: null,
|
|
267
|
+
subscription_distribution: otherSubscriptionDist,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
this.logger.info('Successfully retrieved platform breakdown', {
|
|
271
|
+
role: validatedArgs.role,
|
|
272
|
+
breakdownType: validatedArgs.breakdownType,
|
|
273
|
+
topN,
|
|
274
|
+
topItemsCount: topItems.length,
|
|
275
|
+
hasOther: !!otherItems,
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
startDate,
|
|
279
|
+
endDate,
|
|
280
|
+
role: validatedArgs.role,
|
|
281
|
+
breakdownType: validatedArgs.breakdownType,
|
|
282
|
+
top_items: topItems,
|
|
283
|
+
other_items: otherItems,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
if (error instanceof Error && error.name === 'ZodError') {
|
|
288
|
+
throw new handlers_js_1.ValidationError('Invalid arguments for get_platform_breakdown', {
|
|
289
|
+
details: error.message,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (error instanceof handlers_js_1.ValidationError) {
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
this.logger.error('Failed to get platform breakdown', {}, error);
|
|
296
|
+
// Check if this is a ResponseError from Elasticsearch client
|
|
297
|
+
if (error && typeof error === 'object' && 'body' in error) {
|
|
298
|
+
throw handlers_js_1.ElasticsearchError.fromResponseError(error, 'get_platform_breakdown', args);
|
|
299
|
+
}
|
|
300
|
+
throw new handlers_js_1.ElasticsearchError('Failed to get platform breakdown from Elasticsearch', error, { args });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
exports.GetPlatformBreakdownTool = GetPlatformBreakdownTool;
|
|
305
|
+
//# sourceMappingURL=get-platform-breakdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-platform-breakdown.js","sourceRoot":"","sources":["../../src/tools/get-platform-breakdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ElasticsearchManager } from '../elasticsearch/client.js';
|
|
2
|
+
import { Logger } from '../logger.js';
|
|
3
|
+
export interface GetRatingDistributionArgs {
|
|
4
|
+
ratingType: 'provider' | 'patient' | 'both';
|
|
5
|
+
bucketSize?: number;
|
|
6
|
+
startDate?: string;
|
|
7
|
+
endDate?: string;
|
|
8
|
+
account?: string;
|
|
9
|
+
group?: string;
|
|
10
|
+
subscription?: 'Enterprise' | 'Premium' | 'FVC' | 'BVC' | 'Plus';
|
|
11
|
+
groupBy?: 'none' | 'subscription' | 'account' | 'group';
|
|
12
|
+
}
|
|
13
|
+
export interface RatingBucket {
|
|
14
|
+
range: string;
|
|
15
|
+
count: number;
|
|
16
|
+
percentage: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RatingDistributionItem extends Record<string, any> {
|
|
19
|
+
provider_distribution?: RatingBucket[];
|
|
20
|
+
patient_distribution?: RatingBucket[];
|
|
21
|
+
provider_stats?: {
|
|
22
|
+
total_ratings: number;
|
|
23
|
+
average_rating: number;
|
|
24
|
+
min_rating: number;
|
|
25
|
+
max_rating: number;
|
|
26
|
+
};
|
|
27
|
+
patient_stats?: {
|
|
28
|
+
total_ratings: number;
|
|
29
|
+
average_rating: number;
|
|
30
|
+
min_rating: number;
|
|
31
|
+
max_rating: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface RatingDistributionResult {
|
|
35
|
+
startDate: string;
|
|
36
|
+
endDate: string;
|
|
37
|
+
ratingType: string;
|
|
38
|
+
period: string;
|
|
39
|
+
groupBy: string;
|
|
40
|
+
distribution: RatingDistributionItem | RatingDistributionItem[];
|
|
41
|
+
}
|
|
42
|
+
export declare class GetRatingDistributionTool {
|
|
43
|
+
private elasticsearch;
|
|
44
|
+
private logger;
|
|
45
|
+
constructor(elasticsearch: ElasticsearchManager, logger: Logger);
|
|
46
|
+
execute(args: unknown): Promise<RatingDistributionResult>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=get-rating-distribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-rating-distribution.d.ts","sourceRoot":"","sources":["../../src/tools/get-rating-distribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAkBtC,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IACjE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,OAAO,CAAC;CACzD;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IACjE,qBAAqB,CAAC,EAAE,YAAY,EAAE,CAAC;IACvC,oBAAoB,CAAC,EAAE,YAAY,EAAE,CAAC;IACtC,cAAc,CAAC,EAAE;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;CACjE;AAED,qBAAa,yBAAyB;IACpC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,MAAM,CAAS;gBAEX,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;IAKzD,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC;CA2ShE"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetRatingDistributionTool = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const handlers_js_1 = require("../errors/handlers.js");
|
|
6
|
+
const date_math_js_1 = require("../utils/date-math.js");
|
|
7
|
+
const aggregation_limits_js_1 = require("../utils/aggregation-limits.js");
|
|
8
|
+
const field_constants_js_1 = require("../utils/field-constants.js");
|
|
9
|
+
const GetRatingDistributionArgsSchema = zod_1.z.object({
|
|
10
|
+
ratingType: zod_1.z.enum(['provider', 'patient', 'both']).describe('Type of rating to analyze: "provider", "patient", or "both"'),
|
|
11
|
+
bucketSize: zod_1.z.number().int().min(1).max(5).optional().default(1).describe('Rating bucket size (default: 1, e.g., 1 = 1-2, 2-3, 3-4, etc.)'),
|
|
12
|
+
startDate: zod_1.z.string().optional().describe('Start date in ISO format (YYYY-MM-DD) or date math (e.g., "now-30d", "now-1y"). Defaults to "now-30d"'),
|
|
13
|
+
endDate: zod_1.z.string().optional().describe('End date in ISO format (YYYY-MM-DD) or date math (e.g., "now"). Defaults to "now"'),
|
|
14
|
+
account: zod_1.z.string().optional().describe('Optional account name to filter by'),
|
|
15
|
+
group: zod_1.z.string().optional().describe('Optional group name to filter by'),
|
|
16
|
+
subscription: zod_1.z.enum(['Enterprise', 'Premium', 'FVC', 'BVC', 'Plus']).optional().describe('Optional subscription tier to filter by'),
|
|
17
|
+
groupBy: zod_1.z.enum(['none', 'subscription', 'account', 'group']).optional().default('none').describe('Optional grouping dimension (default: none). When set, returns separate distributions for each group value.'),
|
|
18
|
+
}).strict();
|
|
19
|
+
class GetRatingDistributionTool {
|
|
20
|
+
elasticsearch;
|
|
21
|
+
logger;
|
|
22
|
+
constructor(elasticsearch, logger) {
|
|
23
|
+
this.elasticsearch = elasticsearch;
|
|
24
|
+
this.logger = logger.child({ tool: 'get-rating-distribution' });
|
|
25
|
+
}
|
|
26
|
+
async execute(args) {
|
|
27
|
+
try {
|
|
28
|
+
const validatedArgs = GetRatingDistributionArgsSchema.parse(args);
|
|
29
|
+
const bucketSize = validatedArgs.bucketSize || 1;
|
|
30
|
+
let startDate = validatedArgs.startDate || 'now-30d';
|
|
31
|
+
let endDate = validatedArgs.endDate || 'now';
|
|
32
|
+
const groupBy = validatedArgs.groupBy || 'none';
|
|
33
|
+
// Safeguard: cap time period to prevent data limit errors
|
|
34
|
+
// When grouping is enabled, this tool aggregates all entities which can be memory-intensive
|
|
35
|
+
const maxDays = groupBy !== 'none' ? 60 : 180; // Stricter limit when grouping
|
|
36
|
+
const { startDate: adjustedStartDate, endDate: adjustedEndDate } = (0, date_math_js_1.capTimePeriod)(startDate, endDate, maxDays, this.logger);
|
|
37
|
+
startDate = adjustedStartDate;
|
|
38
|
+
endDate = adjustedEndDate;
|
|
39
|
+
this.logger.info('Getting rating distribution', {
|
|
40
|
+
ratingType: validatedArgs.ratingType,
|
|
41
|
+
bucketSize,
|
|
42
|
+
startDate,
|
|
43
|
+
endDate,
|
|
44
|
+
account: validatedArgs.account,
|
|
45
|
+
group: validatedArgs.group,
|
|
46
|
+
subscription: validatedArgs.subscription,
|
|
47
|
+
groupBy,
|
|
48
|
+
});
|
|
49
|
+
const client = this.elasticsearch.getClient();
|
|
50
|
+
const index = field_constants_js_1.FIELD_CONSTANTS.index;
|
|
51
|
+
const timeField = field_constants_js_1.FIELD_CONSTANTS.timeField;
|
|
52
|
+
const testVisitField = field_constants_js_1.FIELD_CONSTANTS.testVisitField;
|
|
53
|
+
const accountField = field_constants_js_1.FIELD_CONSTANTS.accountField;
|
|
54
|
+
const groupField = field_constants_js_1.FIELD_CONSTANTS.groupField;
|
|
55
|
+
const subscriptionField = field_constants_js_1.FIELD_CONSTANTS.subscriptionField;
|
|
56
|
+
const providerRatingField = field_constants_js_1.FIELD_CONSTANTS.providerRatingField;
|
|
57
|
+
const patientRatingField = field_constants_js_1.FIELD_CONSTANTS.patientRatingField;
|
|
58
|
+
const callDurationField = field_constants_js_1.FIELD_CONSTANTS.callDurationField;
|
|
59
|
+
const meetingBasedField = field_constants_js_1.FIELD_CONSTANTS.meetingBasedField;
|
|
60
|
+
const filters = [
|
|
61
|
+
{
|
|
62
|
+
range: {
|
|
63
|
+
[timeField]: {
|
|
64
|
+
gte: startDate,
|
|
65
|
+
lt: endDate,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
term: {
|
|
71
|
+
[testVisitField]: 'No',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
bool: {
|
|
76
|
+
should: [
|
|
77
|
+
{ exists: { field: callDurationField } },
|
|
78
|
+
{ term: { [meetingBasedField]: false } },
|
|
79
|
+
],
|
|
80
|
+
minimum_should_match: 1,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
if (validatedArgs.account) {
|
|
85
|
+
filters.push({
|
|
86
|
+
term: {
|
|
87
|
+
[accountField]: validatedArgs.account,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (validatedArgs.group) {
|
|
92
|
+
filters.push({
|
|
93
|
+
term: {
|
|
94
|
+
[groupField]: validatedArgs.group,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (validatedArgs.subscription) {
|
|
99
|
+
filters.push({
|
|
100
|
+
term: {
|
|
101
|
+
[subscriptionField]: validatedArgs.subscription,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const buildRatingAggs = () => {
|
|
106
|
+
const ratingAggs = {};
|
|
107
|
+
if (validatedArgs.ratingType === 'provider' || validatedArgs.ratingType === 'both') {
|
|
108
|
+
const ranges = [];
|
|
109
|
+
for (let i = 1; i <= 5; i += bucketSize) {
|
|
110
|
+
const to = Math.min(i + bucketSize - 0.1, 5);
|
|
111
|
+
ranges.push({ from: i, to });
|
|
112
|
+
}
|
|
113
|
+
ranges.push({ from: 5, to: 5.1 });
|
|
114
|
+
ratingAggs.provider_distribution = {
|
|
115
|
+
range: {
|
|
116
|
+
field: providerRatingField,
|
|
117
|
+
ranges,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
ratingAggs.provider_stats = {
|
|
121
|
+
stats: {
|
|
122
|
+
field: providerRatingField,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (validatedArgs.ratingType === 'patient' || validatedArgs.ratingType === 'both') {
|
|
127
|
+
const ranges = [];
|
|
128
|
+
for (let i = 1; i <= 5; i += bucketSize) {
|
|
129
|
+
const to = Math.min(i + bucketSize - 0.1, 5);
|
|
130
|
+
ranges.push({ from: i, to });
|
|
131
|
+
}
|
|
132
|
+
ranges.push({ from: 5, to: 5.1 });
|
|
133
|
+
ratingAggs.patient_distribution = {
|
|
134
|
+
range: {
|
|
135
|
+
field: patientRatingField,
|
|
136
|
+
ranges,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
ratingAggs.patient_stats = {
|
|
140
|
+
stats: {
|
|
141
|
+
field: patientRatingField,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return ratingAggs;
|
|
146
|
+
};
|
|
147
|
+
// Build aggregations based on grouping
|
|
148
|
+
let aggs;
|
|
149
|
+
if (groupBy === 'none') {
|
|
150
|
+
aggs = buildRatingAggs();
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
let groupFieldName;
|
|
154
|
+
switch (groupBy) {
|
|
155
|
+
case 'subscription':
|
|
156
|
+
groupFieldName = subscriptionField;
|
|
157
|
+
break;
|
|
158
|
+
case 'account':
|
|
159
|
+
groupFieldName = accountField;
|
|
160
|
+
break;
|
|
161
|
+
case 'group':
|
|
162
|
+
groupFieldName = groupField;
|
|
163
|
+
break;
|
|
164
|
+
default:
|
|
165
|
+
groupFieldName = subscriptionField;
|
|
166
|
+
}
|
|
167
|
+
aggs = {
|
|
168
|
+
by_group: {
|
|
169
|
+
terms: {
|
|
170
|
+
field: groupFieldName,
|
|
171
|
+
size: aggregation_limits_js_1.AGGREGATION_LIMITS.MEDIUM, // Safeguard: cap at 50 to prevent data limits
|
|
172
|
+
},
|
|
173
|
+
aggs: buildRatingAggs(),
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const query = {
|
|
178
|
+
index,
|
|
179
|
+
size: 0,
|
|
180
|
+
body: {
|
|
181
|
+
track_total_hits: false,
|
|
182
|
+
query: {
|
|
183
|
+
bool: {
|
|
184
|
+
filter: filters,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
aggs,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
this.logger.debug('Executing query', { query: JSON.stringify(query, null, 2) });
|
|
191
|
+
const response = await client.search(query);
|
|
192
|
+
const responseAggs = response.aggregations;
|
|
193
|
+
const processDistributionItem = (itemAggs) => {
|
|
194
|
+
const item = {};
|
|
195
|
+
if (itemAggs?.provider_distribution) {
|
|
196
|
+
const buckets = itemAggs.provider_distribution.buckets || [];
|
|
197
|
+
const total = buckets.reduce((sum, b) => sum + (b.doc_count || 0), 0);
|
|
198
|
+
const distribution = buckets.map((bucket) => {
|
|
199
|
+
const count = bucket.doc_count || 0;
|
|
200
|
+
return {
|
|
201
|
+
range: `${bucket.from} - ${bucket.to}`,
|
|
202
|
+
count,
|
|
203
|
+
percentage: total > 0 ? Math.round((count / total) * 100 * 100) / 100 : 0,
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
item.provider_distribution = distribution;
|
|
207
|
+
if (itemAggs?.provider_stats) {
|
|
208
|
+
const stats = itemAggs.provider_stats;
|
|
209
|
+
item.provider_stats = {
|
|
210
|
+
total_ratings: stats.count || 0,
|
|
211
|
+
average_rating: stats.avg ? Math.round(stats.avg * 100) / 100 : 0,
|
|
212
|
+
min_rating: stats.min || 0,
|
|
213
|
+
max_rating: stats.max || 0,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Process patient distribution
|
|
218
|
+
if (itemAggs?.patient_distribution) {
|
|
219
|
+
const buckets = itemAggs.patient_distribution.buckets || [];
|
|
220
|
+
const total = buckets.reduce((sum, b) => sum + (b.doc_count || 0), 0);
|
|
221
|
+
const distribution = buckets.map((bucket) => {
|
|
222
|
+
const count = bucket.doc_count || 0;
|
|
223
|
+
return {
|
|
224
|
+
range: `${bucket.from} - ${bucket.to}`,
|
|
225
|
+
count,
|
|
226
|
+
percentage: total > 0 ? Math.round((count / total) * 100 * 100) / 100 : 0,
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
item.patient_distribution = distribution;
|
|
230
|
+
if (itemAggs?.patient_stats) {
|
|
231
|
+
const stats = itemAggs.patient_stats;
|
|
232
|
+
item.patient_stats = {
|
|
233
|
+
total_ratings: stats.count || 0,
|
|
234
|
+
average_rating: stats.avg ? Math.round(stats.avg * 100) / 100 : 0,
|
|
235
|
+
min_rating: stats.min || 0,
|
|
236
|
+
max_rating: stats.max || 0,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return item;
|
|
241
|
+
};
|
|
242
|
+
let distribution;
|
|
243
|
+
if (groupBy === 'none') {
|
|
244
|
+
distribution = processDistributionItem(responseAggs);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
const valueKey = `${groupBy}_value`;
|
|
248
|
+
const groupBuckets = responseAggs?.by_group?.buckets || [];
|
|
249
|
+
distribution = groupBuckets.map((bucket) => ({
|
|
250
|
+
[valueKey]: bucket.key,
|
|
251
|
+
...processDistributionItem(bucket),
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
this.logger.info('Successfully retrieved rating distribution', {
|
|
255
|
+
ratingType: validatedArgs.ratingType,
|
|
256
|
+
groupBy,
|
|
257
|
+
itemCount: Array.isArray(distribution) ? distribution.length : 1,
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
startDate,
|
|
261
|
+
endDate,
|
|
262
|
+
ratingType: validatedArgs.ratingType,
|
|
263
|
+
period: `${startDate} to ${endDate}`,
|
|
264
|
+
groupBy,
|
|
265
|
+
distribution,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
if (error instanceof Error && error.name === 'ZodError') {
|
|
270
|
+
throw new handlers_js_1.ValidationError('Invalid arguments for get_rating_distribution', {
|
|
271
|
+
details: error.message,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
if (error instanceof handlers_js_1.ValidationError) {
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
this.logger.error('Failed to get rating distribution', {}, error);
|
|
278
|
+
throw new handlers_js_1.ElasticsearchError('Failed to get rating distribution from Elasticsearch', error, { args });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
exports.GetRatingDistributionTool = GetRatingDistributionTool;
|
|
283
|
+
//# sourceMappingURL=get-rating-distribution.js.map
|