@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.
@@ -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 requires HITL approval
35
- if (automationContext.toolsRequiringApproval.includes(toolKey)) {
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
- * Returns an HITL signal for the cloud-agent to process.
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
- * Returns an HITL signal for the cloud-agent to process.
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 HITL signal for cloud-agent to handle
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
- _hitl_required: true,
52
- _hitl_type: "agent_notify",
53
- title: params.title,
54
- content: params.content,
55
- context: params.context,
56
- response_type: params.response_type,
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.44";
1
+ export declare const version = "0.1.46";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '0.1.44';
1
+ export const version = '0.1.46';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolplex/client",
3
- "version": "0.1.44",
3
+ "version": "0.1.46",
4
4
  "author": "ToolPlex LLC",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "description": "The official ToolPlex client for AI agent tool discovery and execution",