@toolplex/client 0.1.44 → 0.1.46
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/mcp-server/toolHandlers/callToolHandler.js +6 -2
- package/dist/mcp-server/toolHandlers/notifyHandler.d.ts +1 -1
- package/dist/mcp-server/toolHandlers/notifyHandler.js +24 -15
- package/dist/mcp-server/toolplexApi/service.d.ts +23 -1
- package/dist/mcp-server/toolplexApi/service.js +62 -0
- package/dist/mcp-server/toolplexApi/types.d.ts +35 -0
- package/dist/src/mcp-server/toolplexApi/service.js +62 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -31,8 +31,12 @@ export async function handleCallTool(params) {
|
|
|
31
31
|
const automationContext = clientContext.automationContext;
|
|
32
32
|
if (automationContext) {
|
|
33
33
|
const toolKey = `${params.server_id}.${params.tool_name}`;
|
|
34
|
-
// Check if tool
|
|
35
|
-
|
|
34
|
+
// Check if this is a pre-approved tool call (from HITL resume)
|
|
35
|
+
const isPreApproved = automationContext.preApprovedToolCall?.server_id === params.server_id &&
|
|
36
|
+
automationContext.preApprovedToolCall?.tool_name === params.tool_name;
|
|
37
|
+
// Check if tool requires HITL approval (skip if pre-approved)
|
|
38
|
+
if (!isPreApproved &&
|
|
39
|
+
automationContext.toolsRequiringApproval.includes(toolKey)) {
|
|
36
40
|
await logger.info(`Tool ${toolKey} requires HITL approval`);
|
|
37
41
|
// Return HITL signal for cloud-agent to handle
|
|
38
42
|
return {
|
|
@@ -3,6 +3,6 @@ import { NotifyParams } from "../../shared/mcpServerTypes.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Handler for the notify tool.
|
|
5
5
|
* Only available in automation mode.
|
|
6
|
-
*
|
|
6
|
+
* Creates a notification via the API and optionally pauses the automation.
|
|
7
7
|
*/
|
|
8
8
|
export declare function handleNotify(params: NotifyParams): Promise<CallToolResult>;
|
|
@@ -4,13 +4,14 @@ const logger = FileLogger;
|
|
|
4
4
|
/**
|
|
5
5
|
* Handler for the notify tool.
|
|
6
6
|
* Only available in automation mode.
|
|
7
|
-
*
|
|
7
|
+
* Creates a notification via the API and optionally pauses the automation.
|
|
8
8
|
*/
|
|
9
9
|
export async function handleNotify(params) {
|
|
10
10
|
const startTime = Date.now();
|
|
11
11
|
await logger.debug(`Handling notify request with params: ${JSON.stringify(params)}`);
|
|
12
12
|
const telemetryLogger = Registry.getTelemetryLogger();
|
|
13
13
|
const clientContext = Registry.getClientContext();
|
|
14
|
+
const apiService = Registry.getToolplexApiService();
|
|
14
15
|
try {
|
|
15
16
|
// Verify we're in automation mode
|
|
16
17
|
if (clientContext.clientMode !== "automation") {
|
|
@@ -32,34 +33,42 @@ export async function handleNotify(params) {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
await logger.info(`Sending HITL notification: ${params.title} (pause: ${params.pause_until_response})`);
|
|
36
|
+
// Call the API to create the notification (and pause if needed)
|
|
37
|
+
const result = await apiService.createAutomationNotification({
|
|
38
|
+
automationId: automationContext.automationId,
|
|
39
|
+
runId: automationContext.runId,
|
|
40
|
+
sessionId: clientContext.sessionId,
|
|
41
|
+
title: params.title,
|
|
42
|
+
content: params.content,
|
|
43
|
+
context: params.context,
|
|
44
|
+
responseType: params.response_type,
|
|
45
|
+
responseOptions: params.response_options,
|
|
46
|
+
pauseUntilResponse: params.pause_until_response,
|
|
47
|
+
notificationRecipients: [{ email: automationContext.notificationEmail }],
|
|
48
|
+
expirationHours: automationContext.expirationHours,
|
|
49
|
+
});
|
|
35
50
|
await telemetryLogger.log("client_notify", {
|
|
36
51
|
success: true,
|
|
37
52
|
log_context: {
|
|
38
53
|
response_type: params.response_type,
|
|
39
54
|
pause_until_response: params.pause_until_response,
|
|
40
55
|
has_context: !!params.context,
|
|
56
|
+
notification_id: result.notificationId,
|
|
41
57
|
},
|
|
42
58
|
latency_ms: Date.now() - startTime,
|
|
43
59
|
});
|
|
44
|
-
// Return
|
|
45
|
-
// The cloud-agent will parse this and create the notification
|
|
60
|
+
// Return simple result - cloud-agent checks for 'paused' flag
|
|
46
61
|
return {
|
|
47
62
|
content: [
|
|
48
63
|
{
|
|
49
64
|
type: "text",
|
|
50
65
|
text: JSON.stringify({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
response_options: params.response_options,
|
|
58
|
-
pause_until_response: params.pause_until_response,
|
|
59
|
-
automation_id: automationContext.automationId,
|
|
60
|
-
run_id: automationContext.runId,
|
|
61
|
-
notification_email: automationContext.notificationEmail,
|
|
62
|
-
expiration_hours: automationContext.expirationHours,
|
|
66
|
+
success: true,
|
|
67
|
+
notificationId: result.notificationId,
|
|
68
|
+
paused: result.paused,
|
|
69
|
+
message: result.paused
|
|
70
|
+
? "Notification sent. Automation paused awaiting response."
|
|
71
|
+
: "Notification sent. Automation continues.",
|
|
63
72
|
}),
|
|
64
73
|
},
|
|
65
74
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreatePlaybookResponse, LogPlaybookUsageResponse, SubmitFeedbackResponse, SecurityAssessment, FeedbackSummaryResponse, LogTelemetryRequest, LogTelemetryBatchResponse, InitResponse, SearchResponse } from "./types.js";
|
|
1
|
+
import { CreatePlaybookResponse, LogPlaybookUsageResponse, SubmitFeedbackResponse, SecurityAssessment, FeedbackSummaryResponse, LogTelemetryRequest, LogTelemetryBatchResponse, InitResponse, SearchResponse, NotificationRecipient } from "./types.js";
|
|
2
2
|
import { ClientContext } from "../clientContext.js";
|
|
3
3
|
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { PlaybookAction } from "../../shared/mcpServerTypes.js";
|
|
@@ -26,4 +26,26 @@ export declare class ToolplexApiService {
|
|
|
26
26
|
logPlaybookUsage(playbookId: string, success: boolean, errorMessage?: string): Promise<LogPlaybookUsageResponse>;
|
|
27
27
|
submitFeedback(targetType: "server" | "playbook", targetId: string, vote: "up" | "down", message?: string, securityAssessment?: SecurityAssessment): Promise<SubmitFeedbackResponse>;
|
|
28
28
|
getFeedbackSummary(): Promise<FeedbackSummaryResponse>;
|
|
29
|
+
/**
|
|
30
|
+
* Create an automation notification (HITL)
|
|
31
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
32
|
+
*
|
|
33
|
+
* @returns Object with notificationId and paused status
|
|
34
|
+
*/
|
|
35
|
+
createAutomationNotification(params: {
|
|
36
|
+
automationId: string;
|
|
37
|
+
runId: string;
|
|
38
|
+
sessionId?: string;
|
|
39
|
+
title: string;
|
|
40
|
+
content: string;
|
|
41
|
+
context?: string;
|
|
42
|
+
responseType: "boolean" | "multi_choice" | "freeform";
|
|
43
|
+
responseOptions?: string[];
|
|
44
|
+
pauseUntilResponse: boolean;
|
|
45
|
+
notificationRecipients: NotificationRecipient[];
|
|
46
|
+
expirationHours: number;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
notificationId: string;
|
|
49
|
+
paused: boolean;
|
|
50
|
+
}>;
|
|
29
51
|
}
|
|
@@ -227,4 +227,66 @@ export class ToolplexApiService {
|
|
|
227
227
|
throw err;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Create an automation notification (HITL)
|
|
232
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
233
|
+
*
|
|
234
|
+
* @returns Object with notificationId and paused status
|
|
235
|
+
*/
|
|
236
|
+
async createAutomationNotification(params) {
|
|
237
|
+
const { automationId, runId, sessionId, title, content, context, responseType, responseOptions, pauseUntilResponse, notificationRecipients, expirationHours, } = params;
|
|
238
|
+
try {
|
|
239
|
+
// Create the notification
|
|
240
|
+
const notificationRequest = {
|
|
241
|
+
automation_id: automationId,
|
|
242
|
+
run_id: runId,
|
|
243
|
+
session_id: sessionId,
|
|
244
|
+
notification_type: "agent_notify",
|
|
245
|
+
title,
|
|
246
|
+
content,
|
|
247
|
+
context,
|
|
248
|
+
response_type: responseType,
|
|
249
|
+
response_options: responseOptions,
|
|
250
|
+
requires_response: pauseUntilResponse,
|
|
251
|
+
notification_recipients: notificationRecipients,
|
|
252
|
+
expiration_hours: expirationHours,
|
|
253
|
+
};
|
|
254
|
+
const response = await fetch(`${this.baseUrl}/cloud/automation-notifications`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: this.getHeadersWithSession(),
|
|
257
|
+
body: JSON.stringify(notificationRequest),
|
|
258
|
+
});
|
|
259
|
+
const notificationResult = await this.handleFetchResponse(response);
|
|
260
|
+
await logger.info(`Created automation notification: ${notificationResult.id}`);
|
|
261
|
+
// If pause is requested, update the run status
|
|
262
|
+
if (pauseUntilResponse) {
|
|
263
|
+
const pauseResponse = await fetch(`${this.baseUrl}/cloud/automation-runs/${runId}/pause`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: this.getHeadersWithSession(),
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
status: "awaiting_response",
|
|
268
|
+
resume_context: {
|
|
269
|
+
pending_notification_id: notificationResult.id,
|
|
270
|
+
paused_at: new Date().toISOString(),
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
if (!pauseResponse.ok) {
|
|
275
|
+
const errorText = await pauseResponse.text();
|
|
276
|
+
await logger.warn(`Failed to pause automation run ${runId}: ${errorText}`);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
await logger.info(`Automation run ${runId} paused awaiting response`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
notificationId: notificationResult.id,
|
|
284
|
+
paused: pauseUntilResponse,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
await logger.error(`Error creating automation notification: ${err}`);
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
230
292
|
}
|
|
@@ -22,6 +22,11 @@ export interface AutomationContext {
|
|
|
22
22
|
expirationHours: number;
|
|
23
23
|
/** Notification instructions from automation config */
|
|
24
24
|
notifyInstructions?: string;
|
|
25
|
+
/** Pre-approved tool call from HITL resume (bypasses approval check) */
|
|
26
|
+
preApprovedToolCall?: {
|
|
27
|
+
server_id: string;
|
|
28
|
+
tool_name: string;
|
|
29
|
+
};
|
|
25
30
|
}
|
|
26
31
|
export interface ClientFlags {
|
|
27
32
|
desktop_commander_server_id: string;
|
|
@@ -143,3 +148,33 @@ export interface SearchResponse {
|
|
|
143
148
|
mcp_servers?: any[];
|
|
144
149
|
playbooks?: any[];
|
|
145
150
|
}
|
|
151
|
+
export interface NotificationRecipient {
|
|
152
|
+
email: string;
|
|
153
|
+
name?: string;
|
|
154
|
+
role?: string;
|
|
155
|
+
}
|
|
156
|
+
export interface CreateAutomationNotificationRequest {
|
|
157
|
+
automation_id: string;
|
|
158
|
+
run_id: string;
|
|
159
|
+
session_id?: string;
|
|
160
|
+
notification_type: "agent_notify" | "tool_approval";
|
|
161
|
+
title: string;
|
|
162
|
+
content: string;
|
|
163
|
+
context?: string;
|
|
164
|
+
response_type: "boolean" | "multi_choice" | "freeform";
|
|
165
|
+
response_options?: string[];
|
|
166
|
+
requires_response: boolean;
|
|
167
|
+
notification_recipients: NotificationRecipient[];
|
|
168
|
+
expiration_hours: number;
|
|
169
|
+
}
|
|
170
|
+
export interface CreateAutomationNotificationResponse {
|
|
171
|
+
id: string;
|
|
172
|
+
decision_token: string;
|
|
173
|
+
}
|
|
174
|
+
export interface PauseAutomationRunRequest {
|
|
175
|
+
status: "awaiting_response";
|
|
176
|
+
resume_context: {
|
|
177
|
+
pending_notification_id: string;
|
|
178
|
+
paused_at: string;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
@@ -227,4 +227,66 @@ export class ToolplexApiService {
|
|
|
227
227
|
throw err;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Create an automation notification (HITL)
|
|
232
|
+
* Optionally pauses the automation run if pauseUntilResponse is true
|
|
233
|
+
*
|
|
234
|
+
* @returns Object with notificationId and paused status
|
|
235
|
+
*/
|
|
236
|
+
async createAutomationNotification(params) {
|
|
237
|
+
const { automationId, runId, sessionId, title, content, context, responseType, responseOptions, pauseUntilResponse, notificationRecipients, expirationHours, } = params;
|
|
238
|
+
try {
|
|
239
|
+
// Create the notification
|
|
240
|
+
const notificationRequest = {
|
|
241
|
+
automation_id: automationId,
|
|
242
|
+
run_id: runId,
|
|
243
|
+
session_id: sessionId,
|
|
244
|
+
notification_type: "agent_notify",
|
|
245
|
+
title,
|
|
246
|
+
content,
|
|
247
|
+
context,
|
|
248
|
+
response_type: responseType,
|
|
249
|
+
response_options: responseOptions,
|
|
250
|
+
requires_response: pauseUntilResponse,
|
|
251
|
+
notification_recipients: notificationRecipients,
|
|
252
|
+
expiration_hours: expirationHours,
|
|
253
|
+
};
|
|
254
|
+
const response = await fetch(`${this.baseUrl}/cloud/automation-notifications`, {
|
|
255
|
+
method: "POST",
|
|
256
|
+
headers: this.getHeadersWithSession(),
|
|
257
|
+
body: JSON.stringify(notificationRequest),
|
|
258
|
+
});
|
|
259
|
+
const notificationResult = await this.handleFetchResponse(response);
|
|
260
|
+
await logger.info(`Created automation notification: ${notificationResult.id}`);
|
|
261
|
+
// If pause is requested, update the run status
|
|
262
|
+
if (pauseUntilResponse) {
|
|
263
|
+
const pauseResponse = await fetch(`${this.baseUrl}/cloud/automation-runs/${runId}/pause`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: this.getHeadersWithSession(),
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
status: "awaiting_response",
|
|
268
|
+
resume_context: {
|
|
269
|
+
pending_notification_id: notificationResult.id,
|
|
270
|
+
paused_at: new Date().toISOString(),
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
if (!pauseResponse.ok) {
|
|
275
|
+
const errorText = await pauseResponse.text();
|
|
276
|
+
await logger.warn(`Failed to pause automation run ${runId}: ${errorText}`);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
await logger.info(`Automation run ${runId} paused awaiting response`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
notificationId: notificationResult.id,
|
|
284
|
+
paused: pauseUntilResponse,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
await logger.error(`Error creating automation notification: ${err}`);
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
230
292
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "0.1.
|
|
1
|
+
export declare const version = "0.1.46";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.1.
|
|
1
|
+
export const version = '0.1.46';
|