@velaro/mcp-server 0.6.99 → 0.6.101
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/package.json +1 -1
- package/server.js +226 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.101",
|
|
4
4
|
"description": "Velaro MCP server — connect Claude and other AI agents directly to your Velaro account: KB, workflows, bots, conversations, contacts, routing, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/server.js
CHANGED
|
@@ -842,18 +842,19 @@ const TOOLS = [
|
|
|
842
842
|
groupBy: { type: 'string', description: '"month" or "week" (default month)' },
|
|
843
843
|
deploymentId: { type: 'number', description: 'Optional website (deployment row id) filter' },
|
|
844
844
|
teamId: { type: 'number', description: 'Optional team filter' },
|
|
845
|
+
includeSecondary: { type: 'boolean', description: 'Also return secondary topics per conversation (needs the site multi-topic setting on). Response becomes { report, secondary: [{ theme, conversations, avgConfidence }] }.' },
|
|
845
846
|
},
|
|
846
847
|
},
|
|
847
848
|
},
|
|
848
849
|
{
|
|
849
850
|
name: 'canned_learning_suggestions',
|
|
850
851
|
description: 'List AI-proposed canned message improvements awaiting human review (learned from low ratings and never-used messages). Each row shows currentText, proposedText, the reason, the signals it learned from, and a review state (pending_review, approved, rejected, rolled_back). Intelligence Suite entitlement required.',
|
|
851
|
-
inputSchema: { type: 'object', properties: { state: { type: 'string', description: 'pending_review (default), approved, rejected, rolled_back, or all' } } },
|
|
852
|
+
inputSchema: { type: 'object', properties: { state: { type: 'string', description: 'pending_review (default), approved, rejected, rolled_back, or all' }, teamId: { type: 'number', description: 'Only suggestions for canned responses on this team. Team managers only ever see their own teams.' } } },
|
|
852
853
|
},
|
|
853
854
|
{
|
|
854
855
|
name: 'canned_learning_generate',
|
|
855
|
-
description: 'Analyze this site canned message usage and ratings and queue AI-proposed improvements for human review. Nothing changes until approved. Capped at 5 messages per run and one run per day; text is PII-redacted before it reaches the model.',
|
|
856
|
-
inputSchema: { type: 'object', properties: {} },
|
|
856
|
+
description: 'Analyze this site canned message usage and ratings and queue AI-proposed improvements for human review. Nothing changes until approved. Capped at 5 messages per run and one run per day (per team when teamId is given); text is PII-redacted before it reaches the model. Team managers must pass a teamId they manage.',
|
|
857
|
+
inputSchema: { type: 'object', properties: { teamId: { type: 'number', description: 'Only generate for canned responses on this team' } } },
|
|
857
858
|
},
|
|
858
859
|
{
|
|
859
860
|
name: 'canned_learning_approve',
|
|
@@ -868,6 +869,11 @@ const TOOLS = [
|
|
|
868
869
|
{
|
|
869
870
|
name: 'canned_learning_edit_summary',
|
|
870
871
|
description: 'Which canned messages agents edit most before sending (last 90 days): canned response id, shortcut, edit count and average similarity of the sent text to the original. This is the edited-before-send evidence the weekly canned message learning job uses. Intelligence Suite entitlement required.',
|
|
872
|
+
inputSchema: { type: 'object', properties: { teamId: { type: 'number', description: 'Only canned responses on this team' } } },
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
name: 'canned_learning_teams',
|
|
876
|
+
description: 'Teams the caller can review canned message learning for: every site team for a site supervisor, only managed teams for a team manager. Use the ids as teamId on the other canned_learning tools.',
|
|
871
877
|
inputSchema: { type: 'object', properties: {} },
|
|
872
878
|
},
|
|
873
879
|
{
|
|
@@ -890,6 +896,16 @@ const TOOLS = [
|
|
|
890
896
|
description: 'Replace the active topic list (max 60 topics, 60 chars each, duplicates removed). Used for new classifications only; existing history is untouched. Optionally load a template first with industry.',
|
|
891
897
|
inputSchema: { type: 'object', properties: { topics: { type: 'array', items: { type: 'string' } }, industry: { type: 'string', description: 'Load a template instead: insurance, healthcare, retail, ecommerce, financial, saas, government, manufacturing' } } },
|
|
892
898
|
},
|
|
899
|
+
{
|
|
900
|
+
name: 'chat_topics_settings_get',
|
|
901
|
+
description: 'Chat Intelligence multi-topic site setting: { themeMultiTopicEnabled (default off), themeReEvalEveryNMessages (1-50, default 5) }. Customer-writable by site supervisors.',
|
|
902
|
+
inputSchema: { type: 'object', properties: {} },
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
name: 'chat_topics_settings_set',
|
|
906
|
+
description: 'Turn multi-topic tracking on or off for this site and/or set how many new visitor messages trigger a topic re-check (1-50). Partial and idempotent: omit a field to leave it unchanged. Supervisor only.',
|
|
907
|
+
inputSchema: { type: 'object', properties: { themeMultiTopicEnabled: { type: 'boolean' }, themeReEvalEveryNMessages: { type: 'number' } } },
|
|
908
|
+
},
|
|
893
909
|
{
|
|
894
910
|
name: 'chat_topics_edit',
|
|
895
911
|
description: 'Merge, rename, retire or group topics. Applied when reports are read, so history follows the new names with zero AI cost. op = merge|rename|retire|group; from = topic names; to = target (merge/rename); group = group name (empty clears).',
|
|
@@ -1134,10 +1150,25 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1134
1150
|
},
|
|
1135
1151
|
{
|
|
1136
1152
|
name: 'survey_upsert',
|
|
1137
|
-
description: 'Create (omit id or set id=0) or update (set id) a survey. body must be the full SurveyViewModel JSON shape (id, name, questions[], each question with type/text/options/required/variable/etc.). Use survey_get on an existing survey to fetch this full shape as a template rather than guessing the question schema from scratch.',
|
|
1138
|
-
inputSchema: {
|
|
1139
|
-
type: 'object',
|
|
1140
|
-
properties: { body: {
|
|
1153
|
+
description: 'Create (omit id or set id=0) or update (set id) a survey. body must be the full SurveyViewModel JSON shape (id, name, questions[], each question with type/text/options/required/variable/etc.). Use survey_get on an existing survey to fetch this full shape as a template rather than guessing the question schema from scratch. Each question also accepts isThemeAnchor (boolean, default false: this answer sets the Chat Intelligence topic) and themeMapping (string: JSON object mapping answer text to a site topic, e.g. "{\\"Pay my bill\\":\\"Billing Questions\\"}"). Both only take effect when the site has the multi-topic setting on.',
|
|
1154
|
+
inputSchema: {
|
|
1155
|
+
type: 'object',
|
|
1156
|
+
properties: { body: {
|
|
1157
|
+
type: 'object',
|
|
1158
|
+
description: 'Full SurveyViewModel JSON',
|
|
1159
|
+
properties: {
|
|
1160
|
+
questions: {
|
|
1161
|
+
type: 'array',
|
|
1162
|
+
items: {
|
|
1163
|
+
type: 'object',
|
|
1164
|
+
properties: {
|
|
1165
|
+
isThemeAnchor: { type: 'boolean', description: 'Use the answer to this question as the Chat Intelligence topic (default false)' },
|
|
1166
|
+
themeMapping: { type: 'string', description: 'JSON object string mapping answer text to a site topic; invalid or empty is stored as null' },
|
|
1167
|
+
},
|
|
1168
|
+
},
|
|
1169
|
+
},
|
|
1170
|
+
},
|
|
1171
|
+
} },
|
|
1141
1172
|
required: ['body'],
|
|
1142
1173
|
},
|
|
1143
1174
|
},
|
|
@@ -1557,6 +1588,23 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1557
1588
|
},
|
|
1558
1589
|
},
|
|
1559
1590
|
|
|
1591
|
+
// ── Dynamics per-team overrides (effective = team override ?? connection default) ──
|
|
1592
|
+
{
|
|
1593
|
+
name: 'dynamics_team_overrides_get',
|
|
1594
|
+
description: 'List per-team (group) Dynamics overrides of custom field mappings and activity type for a Dynamics config, plus the config\'s own "apply to all groups" defaults. Site is resolved server-side.',
|
|
1595
|
+
inputSchema: { type: 'object', properties: { configId: { type: 'number' } }, required: ['configId'] },
|
|
1596
|
+
},
|
|
1597
|
+
{
|
|
1598
|
+
name: 'dynamics_team_overrides_set',
|
|
1599
|
+
description: 'Create/update one team\'s Dynamics override. Apply-if-present: omitted fields are unchanged; an empty string clears that field back to the default. Fields: activityLogicalName (e.g. phonecall, task), customFieldMappingsJson (JSON array string).',
|
|
1600
|
+
inputSchema: { type: 'object', properties: { configId: { type: 'number' }, teamId: { type: 'number' }, activityLogicalName: { type: 'string' }, customFieldMappingsJson: { type: 'string' } }, required: ['configId', 'teamId'] },
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
name: 'dynamics_team_overrides_reset',
|
|
1604
|
+
description: 'Reset a team to the Dynamics default (removes its override).',
|
|
1605
|
+
inputSchema: { type: 'object', properties: { configId: { type: 'number' }, teamId: { type: 'number' } }, required: ['configId', 'teamId'] },
|
|
1606
|
+
},
|
|
1607
|
+
|
|
1560
1608
|
// ── Teams ─────────────────────────────────────────────────────────────────
|
|
1561
1609
|
{
|
|
1562
1610
|
name: 'team_list',
|
|
@@ -2155,6 +2203,62 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
2155
2203
|
required: ['fromIndex', 'toIndex'],
|
|
2156
2204
|
},
|
|
2157
2205
|
},
|
|
2206
|
+
{
|
|
2207
|
+
name: 'safety_events_list',
|
|
2208
|
+
description: "List the site's safety events (emergency, emergency_unconfirmed, therapy_setting_change, fail_closed, output_guardrail_block, visitor_report, off_topic_attempt). Needs the EnableTroubleshootingKnowledge entitlement. Wraps GET SafetyEvents; the site comes from the caller auth, never an argument.",
|
|
2209
|
+
inputSchema: {
|
|
2210
|
+
type: 'object',
|
|
2211
|
+
properties: {
|
|
2212
|
+
from: { type: 'string', description: 'ISO start date/time' },
|
|
2213
|
+
to: { type: 'string', description: 'ISO end date/time' },
|
|
2214
|
+
type: { type: 'string', description: 'One event type' },
|
|
2215
|
+
status: { type: 'string', enum: ['open', 'acknowledged'] },
|
|
2216
|
+
take: { type: 'number', description: 'Page size, default 25' },
|
|
2217
|
+
skip: { type: 'number', description: 'Rows to skip, default 0' },
|
|
2218
|
+
},
|
|
2219
|
+
},
|
|
2220
|
+
},
|
|
2221
|
+
{
|
|
2222
|
+
name: 'safety_events_summary',
|
|
2223
|
+
description: 'Per-day and total safety event counts by type for the last N days (default 7). Wraps GET SafetyEvents/summary.',
|
|
2224
|
+
inputSchema: { type: 'object', properties: { days: { type: 'number', description: 'Default 7, e.g. 30' } } },
|
|
2225
|
+
},
|
|
2226
|
+
{
|
|
2227
|
+
name: 'safety_event_ack',
|
|
2228
|
+
description: 'Mark one safety event as reviewed. Wraps POST SafetyEvents/{id}/acknowledge.',
|
|
2229
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
|
|
2230
|
+
},
|
|
2231
|
+
{
|
|
2232
|
+
name: 'safety_settings_get',
|
|
2233
|
+
description: 'Get the safety alert settings: enabled, emailRecipients, smsRecipients, immediateTypes, digest (off|daily|weekly), threshold {count, windowMinutes}. Wraps GET SafetyEvents/settings.',
|
|
2234
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2235
|
+
},
|
|
2236
|
+
{
|
|
2237
|
+
name: 'safety_settings_set',
|
|
2238
|
+
description: 'Change the safety alert settings. Only the fields you pass change; the rest keep their current value. Wraps PUT SafetyEvents/settings (reads the current settings first).',
|
|
2239
|
+
inputSchema: {
|
|
2240
|
+
type: 'object',
|
|
2241
|
+
properties: {
|
|
2242
|
+
enabled: { type: 'boolean' },
|
|
2243
|
+
emailRecipients: { type: 'array', items: { type: 'string' } },
|
|
2244
|
+
smsRecipients: { type: 'array', items: { type: 'string' }, description: 'E.164 numbers, e.g. +15551234567' },
|
|
2245
|
+
immediateTypes: { type: 'array', items: { type: 'string' }, description: 'Event types that alert right away' },
|
|
2246
|
+
digest: { type: 'string', enum: ['off', 'daily', 'weekly'] },
|
|
2247
|
+
thresholdCount: { type: 'number', description: 'Alert when this many events happen inside the window. 0 turns it off.' },
|
|
2248
|
+
thresholdWindowMinutes: { type: 'number', description: '1 to 10080' },
|
|
2249
|
+
},
|
|
2250
|
+
},
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
name: 'safety_settings_test',
|
|
2254
|
+
description: 'Send a test safety alert to the configured recipients. Wraps POST SafetyEvents/settings/test.',
|
|
2255
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2256
|
+
},
|
|
2257
|
+
{
|
|
2258
|
+
name: 'safety_need_help',
|
|
2259
|
+
description: 'Tell the Velaro team the bot is going off the rails and you need help now. Wraps POST SafetyEvents/need-help.',
|
|
2260
|
+
inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'What is happening' } }, required: ['message'] },
|
|
2261
|
+
},
|
|
2158
2262
|
{
|
|
2159
2263
|
name: 'index_move_status',
|
|
2160
2264
|
description: 'Status of one move (moveId) or the recent moves (omit moveId): status, per-document progress, canResume/canAbort/canUndo. Wraps GET IndexMove/Moves[/{id}].',
|
|
@@ -2867,6 +2971,25 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
2867
2971
|
},
|
|
2868
2972
|
},
|
|
2869
2973
|
|
|
2974
|
+
// ── Chat Window launcher copy (per-page launcher label + greeting) ─────────
|
|
2975
|
+
{
|
|
2976
|
+
name: 'chat_window_list',
|
|
2977
|
+
description: 'List chat windows for this site with the launcher label (launcherText) and greeting. Point a Select Chat Window workflow node or Determine Experience Bundle rule at a window to show its label and greeting on specific pages.',
|
|
2978
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
2979
|
+
},
|
|
2980
|
+
{
|
|
2981
|
+
name: 'chat_window_set_launcher_copy',
|
|
2982
|
+
description: 'Set the launcher label (the text pill on the chat button, max 60 chars) and/or the opening greeting (max 256 chars) on one chat window. Omitted fields are left unchanged; an empty string clears the field and the widget falls back to its default. For per-page copy, create one chat window per page type (and per language) and select it with a Select Chat Window workflow node.',
|
|
2983
|
+
inputSchema: {
|
|
2984
|
+
type: 'object',
|
|
2985
|
+
properties: {
|
|
2986
|
+
id: { type: 'number', description: 'Chat window ID (see chat_window_list)' },
|
|
2987
|
+
launcherText: { type: 'string', description: 'Launcher label, e.g. "Troubleshoot my device"' },
|
|
2988
|
+
greeting: { type: 'string', description: 'Opening greeting shown when the window opens' },
|
|
2989
|
+
},
|
|
2990
|
+
required: ['id'],
|
|
2991
|
+
},
|
|
2992
|
+
},
|
|
2870
2993
|
// ── Page Widget Containers ────────────────────────────────────────────────
|
|
2871
2994
|
{
|
|
2872
2995
|
name: 'widget_container_list',
|
|
@@ -3394,6 +3517,18 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
3394
3517
|
},
|
|
3395
3518
|
},
|
|
3396
3519
|
|
|
3520
|
+
// -- Image Analysis (analyze_image) limits (superadmin) --
|
|
3521
|
+
{
|
|
3522
|
+
name: 'image_analysis_limits',
|
|
3523
|
+
description: 'Show a customer site Image Analysis (photo analysis) add-on limits: entitlement, monthly cap (MaxImageAnalysesPerMonth), usage this month, per-chat cap and extra-block size. Velaro admin only. To change the cap use support_set_limit with key MaxImageAnalysesPerMonth.',
|
|
3524
|
+
inputSchema: {
|
|
3525
|
+
type: 'object',
|
|
3526
|
+
properties: {
|
|
3527
|
+
siteId: { type: 'number', description: 'Site ID to check' },
|
|
3528
|
+
},
|
|
3529
|
+
required: ['siteId'],
|
|
3530
|
+
},
|
|
3531
|
+
},
|
|
3397
3532
|
// ── AI Video Avatar management (superadmin) ────────────────────────────────
|
|
3398
3533
|
{
|
|
3399
3534
|
name: 'avatar_get_config',
|
|
@@ -6318,6 +6453,7 @@ async function handleTool(name, args) {
|
|
|
6318
6453
|
qs.set('groupBy', args.groupBy ?? 'month');
|
|
6319
6454
|
if (args.deploymentId != null) qs.set('deploymentId', String(args.deploymentId));
|
|
6320
6455
|
if (args.teamId != null) qs.set('teamId', String(args.teamId));
|
|
6456
|
+
if (args.includeSecondary === true) qs.set('includeSecondary', 'true');
|
|
6321
6457
|
return await messagingGet(`/Reports/chat-intelligence/themes?${qs.toString()}`);
|
|
6322
6458
|
}
|
|
6323
6459
|
case 'chat_topics_get':
|
|
@@ -6326,6 +6462,13 @@ async function handleTool(name, args) {
|
|
|
6326
6462
|
return args.industry
|
|
6327
6463
|
? await messagingPost('/ChatIntelligenceTopics/template', { industry: args.industry })
|
|
6328
6464
|
: await messagingPut('/ChatIntelligenceTopics', { topics: args.topics ?? [] });
|
|
6465
|
+
case 'chat_topics_settings_get':
|
|
6466
|
+
return await messagingGet('/ChatIntelligenceTopics/settings');
|
|
6467
|
+
case 'chat_topics_settings_set':
|
|
6468
|
+
return await messagingPut('/ChatIntelligenceTopics/settings', {
|
|
6469
|
+
themeMultiTopicEnabled: typeof args.themeMultiTopicEnabled === 'boolean' ? args.themeMultiTopicEnabled : null,
|
|
6470
|
+
themeReEvalEveryNMessages: typeof args.themeReEvalEveryNMessages === 'number' ? args.themeReEvalEveryNMessages : null,
|
|
6471
|
+
});
|
|
6329
6472
|
case 'chat_topics_edit':
|
|
6330
6473
|
return await messagingPost('/ChatIntelligenceTopics/mapping', { ops: [{ op: args.op, from: args.from ?? [], to: args.to ?? null, group: args.group ?? null }] });
|
|
6331
6474
|
case 'chat_topics_group_suggestions':
|
|
@@ -6343,15 +6486,17 @@ async function handleTool(name, args) {
|
|
|
6343
6486
|
if (args.confirm) return await messagingPost('/ChatIntelligenceTopics/analysis', { confirm: true });
|
|
6344
6487
|
return { estimate: await messagingGet('/ChatIntelligenceTopics/analysis/estimate'), cached: await messagingGet('/ChatIntelligenceTopics/analysis') };
|
|
6345
6488
|
case 'canned_learning_suggestions':
|
|
6346
|
-
return await messagingGet(`/CannedLearning/suggestions?state=${encodeURIComponent(args.state ?? 'pending_review')}`);
|
|
6489
|
+
return await messagingGet(`/CannedLearning/suggestions?state=${encodeURIComponent(args.state ?? 'pending_review')}${args.teamId != null ? `&teamId=${encodeURIComponent(args.teamId)}` : ''}`);
|
|
6347
6490
|
case 'canned_learning_generate':
|
|
6348
|
-
return await messagingPost('/CannedLearning/generate', {});
|
|
6491
|
+
return await messagingPost('/CannedLearning/generate', { teamId: args.teamId ?? null });
|
|
6492
|
+
case 'canned_learning_teams':
|
|
6493
|
+
return await messagingGet('/CannedLearning/teams');
|
|
6349
6494
|
case 'canned_learning_approve':
|
|
6350
6495
|
return await messagingPost(`/CannedLearning/suggestions/${args.suggestionId}/approve`, { editedText: args.editedText ?? null });
|
|
6351
6496
|
case 'canned_learning_reject':
|
|
6352
6497
|
return await messagingPost(`/CannedLearning/suggestions/${args.suggestionId}/reject`, {});
|
|
6353
6498
|
case 'canned_learning_edit_summary':
|
|
6354
|
-
return await messagingGet(
|
|
6499
|
+
return await messagingGet(`/CannedLearning/edit-events${args.teamId != null ? `?teamId=${encodeURIComponent(args.teamId)}` : ''}`);
|
|
6355
6500
|
case 'canned_learning_record_edit':
|
|
6356
6501
|
return await messagingPost('/CannedLearning/edit-events', { cannedResponseId: args.cannedResponseId, finalText: args.finalText });
|
|
6357
6502
|
case 'canned_learning_rollback':
|
|
@@ -6911,6 +7056,19 @@ async function handleTool(name, args) {
|
|
|
6911
7056
|
return await api('PUT', '/TeamsBot/PushSettings', body);
|
|
6912
7057
|
}
|
|
6913
7058
|
|
|
7059
|
+
case 'dynamics_team_overrides_get':
|
|
7060
|
+
return await api('GET', `/Dynamics/Configs/${Number(args.configId)}/team-overrides`);
|
|
7061
|
+
|
|
7062
|
+
case 'dynamics_team_overrides_set': {
|
|
7063
|
+
const body = {};
|
|
7064
|
+
for (const k of ['activityLogicalName', 'customFieldMappingsJson'])
|
|
7065
|
+
if (args[k] !== undefined) body[k] = args[k];
|
|
7066
|
+
return await api('PUT', `/Dynamics/Configs/${Number(args.configId)}/team-overrides/${Number(args.teamId)}`, body);
|
|
7067
|
+
}
|
|
7068
|
+
|
|
7069
|
+
case 'dynamics_team_overrides_reset':
|
|
7070
|
+
return await api('DELETE', `/Dynamics/Configs/${Number(args.configId)}/team-overrides/${Number(args.teamId)}`);
|
|
7071
|
+
|
|
6914
7072
|
case 'teams_channel_config_get':
|
|
6915
7073
|
return await api('GET', '/TeamsBot/ChannelConfig');
|
|
6916
7074
|
|
|
@@ -7769,6 +7927,35 @@ async function handleTool(name, args) {
|
|
|
7769
7927
|
const r = await messagingPost('/IndexMove/Split/Execute', body);
|
|
7770
7928
|
return JSON.stringify(r, null, 2);
|
|
7771
7929
|
}
|
|
7930
|
+
case 'safety_events_list': {
|
|
7931
|
+
const q = new URLSearchParams();
|
|
7932
|
+
for (const k of ['from', 'to', 'type', 'status']) if (args[k]) q.set(k, String(args[k]));
|
|
7933
|
+
q.set('take', String(args.take ?? 25));
|
|
7934
|
+
q.set('skip', String(args.skip ?? 0));
|
|
7935
|
+
return JSON.stringify(await messagingGet(`/SafetyEvents?${q}`), null, 2);
|
|
7936
|
+
}
|
|
7937
|
+
case 'safety_events_summary':
|
|
7938
|
+
return JSON.stringify(await messagingGet(`/SafetyEvents/summary?days=${Number(args.days) || 7}`), null, 2);
|
|
7939
|
+
case 'safety_event_ack':
|
|
7940
|
+
return JSON.stringify(await messagingPost(`/SafetyEvents/${encodeURIComponent(args.id)}/acknowledge`), null, 2);
|
|
7941
|
+
case 'safety_settings_get':
|
|
7942
|
+
return JSON.stringify(await messagingGet('/SafetyEvents/settings'), null, 2);
|
|
7943
|
+
case 'safety_settings_set': {
|
|
7944
|
+
const cur = (await messagingGet('/SafetyEvents/settings')) ?? {};
|
|
7945
|
+
const next = { ...cur };
|
|
7946
|
+
for (const k of ['enabled', 'emailRecipients', 'smsRecipients', 'immediateTypes', 'digest']) if (args[k] !== undefined) next[k] = args[k];
|
|
7947
|
+
if (args.thresholdCount !== undefined || args.thresholdWindowMinutes !== undefined) {
|
|
7948
|
+
next.threshold = {
|
|
7949
|
+
count: args.thresholdCount ?? cur.threshold?.count ?? 0,
|
|
7950
|
+
windowMinutes: args.thresholdWindowMinutes ?? cur.threshold?.windowMinutes ?? 60,
|
|
7951
|
+
};
|
|
7952
|
+
}
|
|
7953
|
+
return JSON.stringify(await messagingPut('/SafetyEvents/settings', next), null, 2);
|
|
7954
|
+
}
|
|
7955
|
+
case 'safety_settings_test':
|
|
7956
|
+
return JSON.stringify(await messagingPost('/SafetyEvents/settings/test'), null, 2);
|
|
7957
|
+
case 'safety_need_help':
|
|
7958
|
+
return JSON.stringify(await messagingPost('/SafetyEvents/need-help', { message: args.message }), null, 2);
|
|
7772
7959
|
case 'index_move_status': {
|
|
7773
7960
|
const r = await messagingGet(args.moveId
|
|
7774
7961
|
? `/IndexMove/Moves/${encodeURIComponent(args.moveId)}`
|
|
@@ -8723,6 +8910,23 @@ async function handleTool(name, args) {
|
|
|
8723
8910
|
).join('\n');
|
|
8724
8911
|
}
|
|
8725
8912
|
|
|
8913
|
+
case 'chat_window_list': {
|
|
8914
|
+
const r = (await messagingGet('/ChatWindow/list')) ?? [];
|
|
8915
|
+
return JSON.stringify(r.map((w) => ({
|
|
8916
|
+
id: w.id, name: w.name, language: w.languageConfig?.language,
|
|
8917
|
+
launcherText: w.styleConfig?.launcherText ?? null, greeting: w.languageConfig?.greeting ?? null,
|
|
8918
|
+
})), null, 2);
|
|
8919
|
+
}
|
|
8920
|
+
|
|
8921
|
+
case 'chat_window_set_launcher_copy': {
|
|
8922
|
+
if (!args.id) throw new Error('id is required');
|
|
8923
|
+
const body = {};
|
|
8924
|
+
if (args.launcherText !== undefined) body.launcherText = args.launcherText;
|
|
8925
|
+
if (args.greeting !== undefined) body.greeting = args.greeting;
|
|
8926
|
+
if (!Object.keys(body).length) throw new Error('provide launcherText and/or greeting');
|
|
8927
|
+
return JSON.stringify(await messagingPut(`/ChatWindow/${args.id}/launcher-copy`, body), null, 2);
|
|
8928
|
+
}
|
|
8929
|
+
|
|
8726
8930
|
case 'widget_container_get': {
|
|
8727
8931
|
const c = await api('GET', `/PageWidgetContainers/${args.id}`);
|
|
8728
8932
|
return JSON.stringify(c, null, 2);
|
|
@@ -9147,6 +9351,18 @@ async function handleTool(name, args) {
|
|
|
9147
9351
|
}
|
|
9148
9352
|
|
|
9149
9353
|
// ── AI Video Avatar ────────────────────────────────────────────────────
|
|
9354
|
+
// -- Image Analysis limits --
|
|
9355
|
+
case 'image_analysis_limits': {
|
|
9356
|
+
const d = await api('GET', `/ImageAnalysisLimits/superadmin?siteId=${args.siteId}`);
|
|
9357
|
+
return [
|
|
9358
|
+
`Site ${args.siteId}: Image Analysis ${d.entitled === null ? 'entitlement unknown' : d.entitled ? 'ENTITLED' : 'NOT entitled'}`,
|
|
9359
|
+
` Monthly cap: ${d.monthlyCap} (effective ${d.effectiveMonthlyCap}, hard cap, no automatic overage)`,
|
|
9360
|
+
` Used this month: ${d.usedThisMonth === null ? 'unknown' : d.usedThisMonth}`,
|
|
9361
|
+
` Per-chat cap: ${d.perConversationCap}`,
|
|
9362
|
+
` Extra block size: ${d.blockSize}`,
|
|
9363
|
+
].join('\n');
|
|
9364
|
+
}
|
|
9365
|
+
|
|
9150
9366
|
case 'avatar_get_config': {
|
|
9151
9367
|
const data = await api('GET', `/Avatar/superadmin/status?siteId=${args.siteId}`);
|
|
9152
9368
|
if (!data.configured) return `Site ${args.siteId}: AI Video Avatar NOT configured (no saved config).`;
|