n8n-nodes-bgos 1.3.4 → 1.4.0
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/nodes/BGOSAction/BGOSAction.node.js +177 -21
- package/dist/nodes/BGOSAction/handler/eventHandler.d.ts +3 -0
- package/dist/nodes/BGOSAction/handler/eventHandler.js +82 -0
- package/dist/nodes/BGOSAction/techWebhook.d.ts +18 -0
- package/dist/nodes/BGOSAction/techWebhook.js +48 -0
- package/package.json +1 -1
|
@@ -11,8 +11,9 @@ class BGOSAction {
|
|
|
11
11
|
group: ['transform'],
|
|
12
12
|
version: 1,
|
|
13
13
|
subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
|
|
14
|
-
description: 'Interact with the BGOS platform',
|
|
14
|
+
description: 'Interact with the BGOS chat platform. Send/edit/pin/delete messages, ask the user a question, send a message and wait for the reply, fetch chat metadata, manage assistants and files. Usable as an AI agent tool.',
|
|
15
15
|
defaults: { name: 'BGOS Action' },
|
|
16
|
+
usableAsTool: true,
|
|
16
17
|
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
17
18
|
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
18
19
|
credentials: [
|
|
@@ -45,22 +46,40 @@ class BGOSAction {
|
|
|
45
46
|
noDataExpression: true,
|
|
46
47
|
displayOptions: { show: { resource: ['message'] } },
|
|
47
48
|
options: [
|
|
48
|
-
{
|
|
49
|
-
name: 'Delete a Message',
|
|
50
|
-
value: 'deleteMessage',
|
|
51
|
-
description: 'Delete a message from a chat',
|
|
52
|
-
action: 'Delete a message',
|
|
53
|
-
},
|
|
54
49
|
{
|
|
55
50
|
name: 'Send a Message',
|
|
56
51
|
value: 'sendMessage',
|
|
57
|
-
description: '
|
|
52
|
+
description: 'Post a new message to a chat. Use for proactive notifications, assistant replies, status updates, or anything you want to say to the user or another agent. Supports text, file attachments, and tappable inline/modal buttons.',
|
|
58
53
|
action: 'Send a message',
|
|
59
54
|
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Send and Wait for Reply',
|
|
57
|
+
value: 'sendAndWaitForReply',
|
|
58
|
+
description: 'Post a message and BLOCK until the next reply arrives in the chat (default 10 min timeout). Use this when an AI agent calls another agent (or the user) and needs the response back as the tool result. Returns { sentMessageId, replyMessageId, replyText }.',
|
|
59
|
+
action: 'Send a message and wait for reply',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'Edit a Message',
|
|
63
|
+
value: 'editMessage',
|
|
64
|
+
description: 'Replace the text of a previously-sent message in place. Use to update a status message ("Working..." → "Done") instead of spamming new messages. Requires Message ID and User ID.',
|
|
65
|
+
action: 'Edit a message',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Pin or Unpin a Message',
|
|
69
|
+
value: 'pinMessage',
|
|
70
|
+
description: 'Toggle the pinned state of a message. Pinned messages appear in the chat\'s pin bar. Set "Is Pinned" to true to pin or false to unpin.',
|
|
71
|
+
action: 'Pin or unpin a message',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Delete a Message',
|
|
75
|
+
value: 'deleteMessage',
|
|
76
|
+
description: 'Permanently remove a message from a chat. Use sparingly — most workflows should edit the text rather than delete + resend.',
|
|
77
|
+
action: 'Delete a message',
|
|
78
|
+
},
|
|
60
79
|
{
|
|
61
80
|
name: 'Ask User Input',
|
|
62
81
|
value: 'askUserInput',
|
|
63
|
-
description: 'Ask the user 1–4 multiple-choice questions through
|
|
82
|
+
description: 'Ask the user 1–4 multiple-choice questions through a polished modal/sheet (or inline carousel). BLOCKS until answered. Use ONLY when the user is actively in conversation and you need their immediate choice; for async/scheduled prompts use Send a Message with buttons instead.',
|
|
64
83
|
action: 'Ask user input',
|
|
65
84
|
},
|
|
66
85
|
],
|
|
@@ -76,25 +95,31 @@ class BGOSAction {
|
|
|
76
95
|
displayOptions: { show: { resource: ['chat'] } },
|
|
77
96
|
options: [
|
|
78
97
|
{
|
|
79
|
-
name: '
|
|
80
|
-
value: '
|
|
81
|
-
description: '
|
|
82
|
-
action: '
|
|
98
|
+
name: 'Get a Chat',
|
|
99
|
+
value: 'getChat',
|
|
100
|
+
description: 'Fetch chat metadata (title, assistant, ownership, timestamps) by chat ID. Use to gather context before deciding how to respond — e.g. checking the assigned assistant or the chat title.',
|
|
101
|
+
action: 'Get a chat',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'Set Title on a Chat',
|
|
105
|
+
value: 'renameChat',
|
|
106
|
+
description: 'Rename a chat. Use after a meaningful event (e.g. summarising the topic of a conversation, or marking a chat as resolved).',
|
|
107
|
+
action: 'Set title on a chat',
|
|
83
108
|
},
|
|
84
109
|
{
|
|
85
110
|
name: 'Save Chat History',
|
|
86
111
|
value: 'saveChatHistory',
|
|
87
|
-
description: 'Bulk-
|
|
112
|
+
description: 'Bulk-insert a list of messages into a chat. Use for migrations or for replaying conversation history; not for normal sending — use "Send a Message" for that.',
|
|
88
113
|
action: 'Save chat history',
|
|
89
114
|
},
|
|
90
115
|
{
|
|
91
|
-
name: '
|
|
92
|
-
value: '
|
|
93
|
-
description: '
|
|
94
|
-
action: '
|
|
116
|
+
name: 'Delete a Chat',
|
|
117
|
+
value: 'deleteChat',
|
|
118
|
+
description: 'Permanently delete a chat and its messages. Destructive — use only for explicit cleanup tasks.',
|
|
119
|
+
action: 'Delete a chat',
|
|
95
120
|
},
|
|
96
121
|
],
|
|
97
|
-
default: '
|
|
122
|
+
default: 'getChat',
|
|
98
123
|
required: true,
|
|
99
124
|
},
|
|
100
125
|
// ── Assistant operations ──────────────────────────────────────────────
|
|
@@ -251,6 +276,115 @@ class BGOSAction {
|
|
|
251
276
|
description: 'ID of the message to delete. Falls back to message_id / messageId from input data.',
|
|
252
277
|
displayOptions: { show: { resource: ['message'], operation: ['deleteMessage'] } },
|
|
253
278
|
},
|
|
279
|
+
// ── Edit a Message ────────────────────────────────────────────────────
|
|
280
|
+
{
|
|
281
|
+
displayName: 'Message ID',
|
|
282
|
+
name: 'messageId',
|
|
283
|
+
type: 'string',
|
|
284
|
+
default: '',
|
|
285
|
+
placeholder: '456',
|
|
286
|
+
description: 'ID of the message to edit. Falls back to message_id / messageId from input data.',
|
|
287
|
+
displayOptions: { show: { resource: ['message'], operation: ['editMessage'] } },
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
displayName: 'New Text',
|
|
291
|
+
name: 'messageText',
|
|
292
|
+
type: 'string',
|
|
293
|
+
typeOptions: { rows: 4 },
|
|
294
|
+
default: '',
|
|
295
|
+
placeholder: 'Done — here\'s the result:',
|
|
296
|
+
description: 'The new message text. Replaces the existing text entirely. Falls back to the input data\'s text field.',
|
|
297
|
+
displayOptions: { show: { resource: ['message'], operation: ['editMessage'] } },
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
displayName: 'User ID',
|
|
301
|
+
name: 'userId',
|
|
302
|
+
type: 'string',
|
|
303
|
+
default: '',
|
|
304
|
+
placeholder: 'user_xxx',
|
|
305
|
+
description: 'User ID of the message owner (for ownership validation). Falls back to user_id from input data.',
|
|
306
|
+
displayOptions: { show: { resource: ['message'], operation: ['editMessage'] } },
|
|
307
|
+
},
|
|
308
|
+
// ── Pin or Unpin a Message ────────────────────────────────────────────
|
|
309
|
+
{
|
|
310
|
+
displayName: 'Message ID',
|
|
311
|
+
name: 'messageId',
|
|
312
|
+
type: 'string',
|
|
313
|
+
default: '',
|
|
314
|
+
placeholder: '456',
|
|
315
|
+
description: 'ID of the message to pin or unpin. Falls back to message_id / messageId from input data.',
|
|
316
|
+
displayOptions: { show: { resource: ['message'], operation: ['pinMessage'] } },
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
displayName: 'Is Pinned',
|
|
320
|
+
name: 'isPinned',
|
|
321
|
+
type: 'boolean',
|
|
322
|
+
default: true,
|
|
323
|
+
description: 'Whether the message should be pinned (true) or unpinned (false). Pinned messages appear in the chat\'s pin bar.',
|
|
324
|
+
displayOptions: { show: { resource: ['message'], operation: ['pinMessage'] } },
|
|
325
|
+
},
|
|
326
|
+
// ── Send and Wait for Reply ───────────────────────────────────────────
|
|
327
|
+
{
|
|
328
|
+
displayName: 'Assistant ID',
|
|
329
|
+
name: 'assistantId',
|
|
330
|
+
type: 'string',
|
|
331
|
+
default: '',
|
|
332
|
+
placeholder: '42',
|
|
333
|
+
description: 'ID of the assistant sending the message. Falls back to assistantId / assistant_id from input data.',
|
|
334
|
+
displayOptions: { show: { resource: ['message'], operation: ['sendAndWaitForReply'] } },
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
displayName: 'Chat ID',
|
|
338
|
+
name: 'chatId',
|
|
339
|
+
type: 'string',
|
|
340
|
+
default: '',
|
|
341
|
+
placeholder: '123',
|
|
342
|
+
description: 'ID of the chat to post into and listen on. Falls back to chatId / chat_id from input data.',
|
|
343
|
+
displayOptions: { show: { resource: ['message'], operation: ['sendAndWaitForReply'] } },
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
displayName: 'Text',
|
|
347
|
+
name: 'messageText',
|
|
348
|
+
type: 'string',
|
|
349
|
+
typeOptions: { rows: 4 },
|
|
350
|
+
default: '',
|
|
351
|
+
placeholder: 'Hey Ava, can you check on the latest sales numbers?',
|
|
352
|
+
description: 'Message text to post. The next reply in the chat will be returned as the tool result.',
|
|
353
|
+
displayOptions: { show: { resource: ['message'], operation: ['sendAndWaitForReply'] } },
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
displayName: 'User ID',
|
|
357
|
+
name: 'userId',
|
|
358
|
+
type: 'string',
|
|
359
|
+
default: '',
|
|
360
|
+
placeholder: 'user_xxx',
|
|
361
|
+
description: 'User ID who owns the chat — needed to poll its messages. Falls back to user_id / userId from input data.',
|
|
362
|
+
displayOptions: { show: { resource: ['message'], operation: ['sendAndWaitForReply'] } },
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
displayName: 'Additional Fields',
|
|
366
|
+
name: 'replyAdditionalFields',
|
|
367
|
+
type: 'collection',
|
|
368
|
+
placeholder: 'Add Field',
|
|
369
|
+
default: {},
|
|
370
|
+
displayOptions: { show: { resource: ['message'], operation: ['sendAndWaitForReply'] } },
|
|
371
|
+
options: [
|
|
372
|
+
{
|
|
373
|
+
displayName: 'Timeout (Seconds)',
|
|
374
|
+
name: 'replyTimeoutSeconds',
|
|
375
|
+
type: 'number',
|
|
376
|
+
default: 600,
|
|
377
|
+
description: 'How long to wait for a reply before failing the node (default 10 minutes).',
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
displayName: 'Poll Interval (Ms)',
|
|
381
|
+
name: 'replyPollIntervalMs',
|
|
382
|
+
type: 'number',
|
|
383
|
+
default: 2000,
|
|
384
|
+
description: 'How often to check for new messages while waiting (default 2 seconds; minimum 1000).',
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
},
|
|
254
388
|
// ── Ask User Input ────────────────────────────────────────────────────
|
|
255
389
|
{
|
|
256
390
|
displayName: 'Chat ID',
|
|
@@ -395,7 +529,7 @@ class BGOSAction {
|
|
|
395
529
|
default: '',
|
|
396
530
|
placeholder: '123',
|
|
397
531
|
description: 'ID of the chat. Falls back to chat_id / chat.id from input data.',
|
|
398
|
-
displayOptions: { show: { resource: ['chat'], operation: ['renameChat', 'deleteChat', 'saveChatHistory'] } },
|
|
532
|
+
displayOptions: { show: { resource: ['chat'], operation: ['renameChat', 'deleteChat', 'saveChatHistory', 'getChat'] } },
|
|
399
533
|
},
|
|
400
534
|
{
|
|
401
535
|
displayName: 'New Title',
|
|
@@ -557,7 +691,7 @@ class BGOSAction {
|
|
|
557
691
|
type: 'string',
|
|
558
692
|
default: '',
|
|
559
693
|
placeholder: 'user_xxx',
|
|
560
|
-
description: 'Override the user ID. If empty, falls back to user_id from the input data.',
|
|
694
|
+
description: 'Override the user ID. If empty, falls back to user_id from the input data. Optional for "Get a Chat".',
|
|
561
695
|
displayOptions: {
|
|
562
696
|
show: {
|
|
563
697
|
resource: ['chat', 'assistant', 'callback', 'file'],
|
|
@@ -599,6 +733,28 @@ class BGOSAction {
|
|
|
599
733
|
if (operation === 'deleteMessage') {
|
|
600
734
|
nodeParams.deleteMessageId = String(this.getNodeParameter('deleteMessageId', i, '') ?? '');
|
|
601
735
|
}
|
|
736
|
+
if (operation === 'editMessage') {
|
|
737
|
+
nodeParams.messageId = String(this.getNodeParameter('messageId', i, '') ?? '');
|
|
738
|
+
nodeParams.messageText = String(this.getNodeParameter('messageText', i, '') ?? '');
|
|
739
|
+
nodeParams.userId = String(this.getNodeParameter('userId', i, '') ?? '');
|
|
740
|
+
}
|
|
741
|
+
if (operation === 'pinMessage') {
|
|
742
|
+
nodeParams.messageId = String(this.getNodeParameter('messageId', i, '') ?? '');
|
|
743
|
+
nodeParams.isPinned = Boolean(this.getNodeParameter('isPinned', i, true));
|
|
744
|
+
}
|
|
745
|
+
if (operation === 'sendAndWaitForReply') {
|
|
746
|
+
nodeParams.assistantId = String(this.getNodeParameter('assistantId', i, '') ?? '');
|
|
747
|
+
nodeParams.chatId = String(this.getNodeParameter('chatId', i, '') ?? '');
|
|
748
|
+
nodeParams.messageText = String(this.getNodeParameter('messageText', i, '') ?? '');
|
|
749
|
+
nodeParams.userId = String(this.getNodeParameter('userId', i, '') ?? '');
|
|
750
|
+
const replyAdditional = this.getNodeParameter('replyAdditionalFields', i, {});
|
|
751
|
+
nodeParams.replyTimeoutSeconds = Number(replyAdditional.replyTimeoutSeconds ?? 600);
|
|
752
|
+
nodeParams.replyPollIntervalMs = Number(replyAdditional.replyPollIntervalMs ?? 2000);
|
|
753
|
+
}
|
|
754
|
+
if (operation === 'getChat') {
|
|
755
|
+
nodeParams.chatId = String(this.getNodeParameter('chatId', i, '') ?? '');
|
|
756
|
+
nodeParams.userId = String(this.getNodeParameter('userId', i, '') ?? '');
|
|
757
|
+
}
|
|
602
758
|
if (operation === 'askUserInput') {
|
|
603
759
|
nodeParams.chatId = String(this.getNodeParameter('chatId', i, '') ?? '');
|
|
604
760
|
nodeParams.userId = String(this.getNodeParameter('askUserId', i, '') ?? '');
|
|
@@ -38,6 +38,9 @@ type NodeParams = {
|
|
|
38
38
|
askTimeoutSeconds?: number;
|
|
39
39
|
askPollIntervalMs?: number;
|
|
40
40
|
renderMode?: string;
|
|
41
|
+
isPinned?: boolean;
|
|
42
|
+
replyTimeoutSeconds?: number;
|
|
43
|
+
replyPollIntervalMs?: number;
|
|
41
44
|
[key: string]: unknown;
|
|
42
45
|
};
|
|
43
46
|
export declare function handleEventByType(this: IExecuteFunctions, eventType: string, eventData: Record<string, unknown>, nodeParams: NodeParams): Promise<unknown>;
|
|
@@ -81,6 +81,80 @@ async function handleEventByType(eventType, eventData, nodeParams) {
|
|
|
81
81
|
}
|
|
82
82
|
return await techWebhook_1.deleteMessage.call(this, apiOptions, String(messageId));
|
|
83
83
|
}
|
|
84
|
+
case 'editMessage': {
|
|
85
|
+
const apiOptions = getApiOptions(nodeParams);
|
|
86
|
+
const messageId = nodeParams.messageId || (eventData.message_id ?? eventData.messageId ?? message?.id);
|
|
87
|
+
const userId = (nodeParams.userId ?? eventData.user_id ?? eventData.userId);
|
|
88
|
+
const newText = (nodeParams.messageText ?? '').trim() || (eventData.text ?? message?.text ?? '');
|
|
89
|
+
if (!messageId || !userId || !newText) {
|
|
90
|
+
throw new Error('Message ID, User ID, and Text are required for Edit a Message. Set the fields or make sure input data contains message_id, user_id, and text.');
|
|
91
|
+
}
|
|
92
|
+
return await techWebhook_1.editMessageText.call(this, apiOptions, userId, String(messageId), String(newText));
|
|
93
|
+
}
|
|
94
|
+
case 'pinMessage': {
|
|
95
|
+
const apiOptions = getApiOptions(nodeParams);
|
|
96
|
+
const messageId = nodeParams.messageId || (eventData.message_id ?? eventData.messageId ?? message?.id);
|
|
97
|
+
if (!messageId) {
|
|
98
|
+
throw new Error('Message ID is required for Pin/Unpin a Message. Set the field or make sure input data contains message_id.');
|
|
99
|
+
}
|
|
100
|
+
// pinState may come from the node param or input data; default to true (pin)
|
|
101
|
+
const pinStateRaw = nodeParams.isPinned ?? eventData.isPinned ?? eventData.is_pinned ?? true;
|
|
102
|
+
const isPinned = pinStateRaw === true || pinStateRaw === 'true';
|
|
103
|
+
return await techWebhook_1.setMessagePinned.call(this, apiOptions, String(messageId), isPinned);
|
|
104
|
+
}
|
|
105
|
+
case 'sendAndWaitForReply': {
|
|
106
|
+
const apiOptions = getApiOptions(nodeParams);
|
|
107
|
+
const assistantId = nodeParams.assistantId || (eventData.assistantId ?? eventData.assistant_id ?? assistant?.id);
|
|
108
|
+
const chatId = nodeParams.chatId || (eventData.chatId ?? eventData.chat_id ?? chat?.id ?? message?.chatId);
|
|
109
|
+
const userId = (nodeParams.userId ?? eventData.user_id ?? eventData.userId);
|
|
110
|
+
const text = (nodeParams.messageText ?? '').trim() || (eventData.text ?? message?.text ?? '');
|
|
111
|
+
if (!assistantId || !chatId || !userId || !text) {
|
|
112
|
+
throw new Error('Assistant ID, Chat ID, User ID, and Text are required for Send and Wait for Reply.');
|
|
113
|
+
}
|
|
114
|
+
// Step 1: post the outgoing message and capture its id
|
|
115
|
+
const sendResult = (await techWebhook_1.sendMessageToBackend.call(this, apiOptions, {
|
|
116
|
+
assistantId: assistantId,
|
|
117
|
+
chatId: chatId,
|
|
118
|
+
sender: 'assistant',
|
|
119
|
+
text,
|
|
120
|
+
}));
|
|
121
|
+
const sentMessageId = Number(sendResult?.id
|
|
122
|
+
?? sendResult?.message?.id
|
|
123
|
+
?? 0);
|
|
124
|
+
if (!sentMessageId) {
|
|
125
|
+
throw new Error('Could not determine sent message ID from BGOS response — cannot wait for reply.');
|
|
126
|
+
}
|
|
127
|
+
// Step 2: poll the chat for any new message with id > sentMessageId
|
|
128
|
+
const timeoutSeconds = Number(nodeParams.replyTimeoutSeconds ?? 600);
|
|
129
|
+
const pollIntervalMs = Math.max(1000, Number(nodeParams.replyPollIntervalMs ?? 2000));
|
|
130
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
131
|
+
while (Date.now() < deadline) {
|
|
132
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
133
|
+
try {
|
|
134
|
+
const data = await techWebhook_1.getChatMessages.call(this, apiOptions, Number(chatId), userId);
|
|
135
|
+
// Cast to a permissive shape — backend returns extra fields beyond ChatMessageEntry
|
|
136
|
+
const msgs = (data?.messages ?? []);
|
|
137
|
+
for (const entry of msgs) {
|
|
138
|
+
const m = (entry.message ?? entry);
|
|
139
|
+
const id = Number(m.id ?? 0);
|
|
140
|
+
const replyText = m.text;
|
|
141
|
+
if (id > sentMessageId && replyText) {
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
sentMessageId,
|
|
145
|
+
replyMessageId: id,
|
|
146
|
+
replyText,
|
|
147
|
+
raw: entry,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Network blip — keep polling.
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
throw new Error(`Timed out after ${timeoutSeconds}s waiting for a reply to message ${sentMessageId} in chat ${chatId}.`);
|
|
157
|
+
}
|
|
84
158
|
case 'askUserInput': {
|
|
85
159
|
const apiOptions = getApiOptions(nodeParams);
|
|
86
160
|
const chatId = nodeParams.chatId || (eventData.chatId ?? eventData.chat_id ?? chat?.id ?? message?.chatId);
|
|
@@ -243,6 +317,14 @@ async function handleEventByType(eventType, eventData, nodeParams) {
|
|
|
243
317
|
throw new Error('Chat ID is required for Delete a Chat.');
|
|
244
318
|
return await techWebhook_1.deleteChat.call(this, getApiOptions(nodeParams), userId, String(chatId));
|
|
245
319
|
}
|
|
320
|
+
case 'getChat': {
|
|
321
|
+
const apiOptions = getApiOptions(nodeParams);
|
|
322
|
+
const chatId = nodeParams.chatId || (eventData.chat_id ?? eventData.chatId ?? chat?.id);
|
|
323
|
+
if (!chatId)
|
|
324
|
+
throw new Error('Chat ID is required for Get a Chat.');
|
|
325
|
+
const userId = (nodeParams.userId ?? eventData.user_id ?? eventData.userId);
|
|
326
|
+
return await techWebhook_1.getChat.call(this, apiOptions, String(chatId), userId);
|
|
327
|
+
}
|
|
246
328
|
case 'saveChatHistory': {
|
|
247
329
|
const userId = (nodeParams.userId ?? eventData.user_id ?? eventData.userId);
|
|
248
330
|
if (!userId)
|
|
@@ -18,6 +18,24 @@ export declare function saveChatHistory(this: IExecuteFunctions, options: BgosAp
|
|
|
18
18
|
export declare function deleteMessage(this: IExecuteFunctions, options: BgosApiOptions, messageId: string | number): Promise<{
|
|
19
19
|
success: boolean;
|
|
20
20
|
}>;
|
|
21
|
+
/**
|
|
22
|
+
* PATCH /api/v1/messages/:id — update the text of an existing message.
|
|
23
|
+
* Useful for status-updates-in-place (e.g. "Working..." → "Done"), replacing
|
|
24
|
+
* the prior approach of sending a new message every time.
|
|
25
|
+
*/
|
|
26
|
+
export declare function editMessageText(this: IExecuteFunctions, options: BgosApiOptions, userId: string, messageId: string | number, text: string): Promise<unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* PATCH /api/v1/messages/:id/pin — toggle the pin state of a message.
|
|
29
|
+
* Body { isPinned: boolean }. Backend stamps pinned_at when true,
|
|
30
|
+
* clears it when false. Emits a message_pinned WebSocket event.
|
|
31
|
+
*/
|
|
32
|
+
export declare function setMessagePinned(this: IExecuteFunctions, options: BgosApiOptions, messageId: string | number, isPinned: boolean): Promise<unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* GET /api/v1/chats/:chatId?userId=... — fetch chat metadata (title,
|
|
35
|
+
* assistantId, ownership). Useful for AI agents that need context before
|
|
36
|
+
* deciding how to respond.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getChat(this: IExecuteFunctions, options: BgosApiOptions, chatId: string | number, userId?: string): Promise<unknown>;
|
|
21
39
|
export declare function sendMessageToBackend(this: IExecuteFunctions, options: BgosApiOptions, payload: {
|
|
22
40
|
assistantId: string | number;
|
|
23
41
|
chatId: string | number;
|
|
@@ -7,6 +7,9 @@ exports.renameChat = renameChat;
|
|
|
7
7
|
exports.deleteChat = deleteChat;
|
|
8
8
|
exports.saveChatHistory = saveChatHistory;
|
|
9
9
|
exports.deleteMessage = deleteMessage;
|
|
10
|
+
exports.editMessageText = editMessageText;
|
|
11
|
+
exports.setMessagePinned = setMessagePinned;
|
|
12
|
+
exports.getChat = getChat;
|
|
10
13
|
exports.sendMessageToBackend = sendMessageToBackend;
|
|
11
14
|
exports.postAskQuestion = postAskQuestion;
|
|
12
15
|
exports.getChatMessages = getChatMessages;
|
|
@@ -97,6 +100,51 @@ async function deleteMessage(options, messageId) {
|
|
|
97
100
|
});
|
|
98
101
|
return { success: true };
|
|
99
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* PATCH /api/v1/messages/:id — update the text of an existing message.
|
|
105
|
+
* Useful for status-updates-in-place (e.g. "Working..." → "Done"), replacing
|
|
106
|
+
* the prior approach of sending a new message every time.
|
|
107
|
+
*/
|
|
108
|
+
async function editMessageText(options, userId, messageId, text) {
|
|
109
|
+
const url = `${options.baseUrl.replace(/\/$/, '')}/api/v1/messages/${messageId}`;
|
|
110
|
+
return this.helpers.httpRequest({
|
|
111
|
+
method: 'PATCH',
|
|
112
|
+
url,
|
|
113
|
+
headers: buildHeaders(options.apiKey),
|
|
114
|
+
body: { userId, text },
|
|
115
|
+
json: true,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* PATCH /api/v1/messages/:id/pin — toggle the pin state of a message.
|
|
120
|
+
* Body { isPinned: boolean }. Backend stamps pinned_at when true,
|
|
121
|
+
* clears it when false. Emits a message_pinned WebSocket event.
|
|
122
|
+
*/
|
|
123
|
+
async function setMessagePinned(options, messageId, isPinned) {
|
|
124
|
+
const url = `${options.baseUrl.replace(/\/$/, '')}/api/v1/messages/${messageId}/pin`;
|
|
125
|
+
return this.helpers.httpRequest({
|
|
126
|
+
method: 'PATCH',
|
|
127
|
+
url,
|
|
128
|
+
headers: buildHeaders(options.apiKey),
|
|
129
|
+
body: { isPinned },
|
|
130
|
+
json: true,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* GET /api/v1/chats/:chatId?userId=... — fetch chat metadata (title,
|
|
135
|
+
* assistantId, ownership). Useful for AI agents that need context before
|
|
136
|
+
* deciding how to respond.
|
|
137
|
+
*/
|
|
138
|
+
async function getChat(options, chatId, userId) {
|
|
139
|
+
const qs = userId ? `?userId=${encodeURIComponent(userId)}` : '';
|
|
140
|
+
const url = `${options.baseUrl.replace(/\/$/, '')}/api/v1/chats/${chatId}${qs}`;
|
|
141
|
+
return this.helpers.httpRequest({
|
|
142
|
+
method: 'GET',
|
|
143
|
+
url,
|
|
144
|
+
headers: buildHeaders(options.apiKey),
|
|
145
|
+
json: true,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
100
148
|
async function sendMessageToBackend(options, payload) {
|
|
101
149
|
const url = `${options.baseUrl.replace(/\/$/, '')}/api/v1/send-message`;
|
|
102
150
|
const body = {
|