@learningsuite/n8n-nodes-learningsuite 1.2.6 → 1.3.4

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.
Files changed (28) hide show
  1. package/README.md +41 -12
  2. package/dist/nodes/LearningSuite/LearningSuite.node.d.ts +7 -1
  3. package/dist/nodes/LearningSuite/LearningSuite.node.js +2 -0
  4. package/dist/nodes/LearningSuite/LearningSuiteTrigger.node.d.ts +7 -1
  5. package/dist/nodes/LearningSuite/LearningSuiteTrigger.node.js +14 -0
  6. package/dist/nodes/LearningSuite/descriptions/ai.properties.js +86 -0
  7. package/dist/nodes/LearningSuite/descriptions/customFields.properties.js +138 -17
  8. package/dist/nodes/LearningSuite/descriptions/trigger.instant.properties.js +32 -0
  9. package/dist/nodes/LearningSuite/descriptions/webhook.properties.js +35 -0
  10. package/dist/nodes/LearningSuite/descriptions/webhook.sampleData.properties.js +26 -0
  11. package/dist/nodes/LearningSuite/execute/ai.handlers.d.ts +3 -0
  12. package/dist/nodes/LearningSuite/execute/ai.handlers.js +44 -0
  13. package/dist/nodes/LearningSuite/execute/customFields.handlers.d.ts +1 -0
  14. package/dist/nodes/LearningSuite/execute/customFields.handlers.js +273 -22
  15. package/dist/nodes/LearningSuite/execute/webhook.handlers.js +16 -0
  16. package/dist/nodes/LearningSuite/methods/loadOptions/ai.loadOptions.d.ts +3 -0
  17. package/dist/nodes/LearningSuite/methods/loadOptions/ai.loadOptions.js +11 -0
  18. package/dist/nodes/LearningSuite/methods/loadOptions/common.d.ts +1 -0
  19. package/dist/nodes/LearningSuite/methods/loadOptions/common.js +5 -0
  20. package/dist/nodes/LearningSuite/methods/loadOptions/customFields.loadOptions.d.ts +8 -4
  21. package/dist/nodes/LearningSuite/methods/loadOptions/customFields.loadOptions.js +76 -3
  22. package/dist/nodes/LearningSuite/shared/customFields.helpers.js +1 -4
  23. package/dist/nodes/LearningSuite/shared/customFields.shared.d.ts +1 -0
  24. package/dist/nodes/LearningSuite/shared/customFields.upload.d.ts +1 -1
  25. package/dist/nodes/LearningSuite/shared/customFields.upload.js +11 -10
  26. package/dist/nodes/LearningSuite/shared/request.d.ts +3 -0
  27. package/dist/nodes/LearningSuite/shared/request.js +18 -0
  28. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # n8n-nodes-learningsuite
2
2
 
3
- ![n8n](https://img.shields.io/badge/n8n-1.113.0+-brightgreen)
3
+ ![n8n](https://img.shields.io/badge/n8n-2.17.2+-brightgreen)
4
4
 
5
- ![Version](https://img.shields.io/badge/version-0.1.0-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.2.3-blue)
6
6
 
7
7
  ![License](https://img.shields.io/badge/license-MIT-green)
8
8
 
@@ -20,9 +20,9 @@ This community node uses the public LearningSuite API and is not affiliated with
20
20
 
21
21
  ## 🚀 Features
22
22
 
23
- - **14 resources** fully supported (Member, Course, Group, Bundle, Hub, Module, Community, Custom Fields, Popup, Webhook, Role, User, Team Member, AI, API Call)
24
- - **87 operations** for maximum flexibility
25
- - **Instant trigger (webhook-based)** with 17 event types for real-time automation
23
+ - **15 resources** fully supported (Member, Course, Group, Bundle, Hub, Module, Community, Custom Fields, Popup, Webhook, Role, User, Team Member, AI, API Call)
24
+ - **90 action endpoints** for maximum flexibility
25
+ - **Instant trigger (webhook-based)** with 18 event types for real-time automation
26
26
  - **Polling trigger** with 11 event types for scheduled polling
27
27
  - **Flexible API call** resource for custom endpoints
28
28
 
@@ -64,12 +64,13 @@ This community node uses the public LearningSuite API and is not affiliated with
64
64
  - Get community areas, get community badges, get community forums, get community posts
65
65
  - Create community post comment
66
66
 
67
- ### 🔧 **Custom Fields** (13 operations)
67
+ ### 🔧 **Custom Fields** (14 operations)
68
68
 
69
69
  - Get cards, get cards (expanded), get categories, get definitions
70
70
  - Get field values, get store, get store values
71
71
  - Get profile by card, get profiles, get profiles (expanded)
72
72
  - Set field value, set multiple field values, update profile field
73
+ - Upload file from URL
73
74
 
74
75
  ### 🎯 **Popup** (4 operations)
75
76
 
@@ -87,9 +88,9 @@ This community node uses the public LearningSuite API and is not affiliated with
87
88
 
88
89
  - Send push notification
89
90
 
90
- ### 🤖 **AI** (1 operation)
91
+ ### 🤖 **AI** (3 operations)
91
92
 
92
- - RAG Chat
93
+ - Get agent actions, get AI agents, RAG Chat
93
94
 
94
95
  ### 🛡️ **Role** (1 operation)
95
96
 
@@ -106,6 +107,7 @@ The LearningSuite trigger supports the following events:
106
107
  ### ⚡ Instant Trigger Events (Webhook)
107
108
 
108
109
  - ✅ Community Post Commented
110
+ - ✅ Agent Action Executed
109
111
  - ✅ Community Post Created
110
112
  - ✅ Community Post Moderated
111
113
  - ✅ Course Member Added
@@ -258,6 +260,19 @@ docker.n8n.io/n8nio/n8n
258
260
 
259
261
  ```
260
262
 
263
+ ### Custom Field File Uploads
264
+
265
+ The Custom Fields resource supports file, image, video, and audio custom fields.
266
+
267
+ - Use **Set Field Value**, **Set Multiple Field Values**, or **Update Profile Field** when the file is available as n8n binary data.
268
+ - Use **Upload File From URL** when LearningSuite should download a public file URL and append the returned file value to the selected custom field.
269
+ - File fields support **File Value Mode**:
270
+ - **Add**: append new file values and fail if the custom field limit would be exceeded
271
+ - **Replace**: replace existing file values with the uploaded file values
272
+ - **Replace if Limit Reached**: append while possible, otherwise replace existing file values
273
+ - The node respects the LearningSuite file limits defined on the custom field, such as `maxFiles`, `maxImages`, `maxVideos`, and `maxAudios`.
274
+ - For custom field cards with multiple profiles, use Profile ID, Profile Index, or Profile Name to target a specific profile. If the card does not allow multiple profiles, profile parameters are ignored and the default profile is used.
275
+
261
276
  ### ⚡ Instant Webhook Trigger Setup
262
277
 
263
278
  ```
@@ -352,15 +367,29 @@ npm test
352
367
 
353
368
  ## 📝 Changelog
354
369
 
370
+ ### Version 1.2.3 (current)
371
+
372
+ #### Custom Fields File Uploads
373
+
374
+ - ✅ Upload file from public URL
375
+
376
+ - ✅ Binary uploads for file, image, video, and audio custom fields
377
+
378
+ - ✅ File Value Mode: add, replace, and replace when the field limit is reached
379
+
380
+ - ✅ Respect custom field file limits (`maxFiles`, `maxImages`, `maxVideos`, `maxAudios`)
381
+
382
+ - ✅ Improved handling for custom field profile cards and default profiles
383
+
355
384
  ### Version 0.1.0 (2025-09-23)
356
385
 
357
- #### 🎉 Initial Release
386
+ #### Initial Release
358
387
 
359
388
  - ✅ Full LearningSuite API integration
360
389
 
361
- - ✅ 14 resources with 87 operations
390
+ - ✅ 15 resources with 90 action endpoints
362
391
 
363
- - ✅ Webhook triggers with 17 event types for real-time automation
392
+ - ✅ Webhook triggers with 18 event types for real-time automation
364
393
 
365
394
  - ✅ Polling triggers with 11 event types
366
395
 
@@ -376,7 +405,7 @@ npm test
376
405
 
377
406
  ## 🛠️ Compatibility
378
407
 
379
- - **n8n Version**: 1.112.3+ (tested with latest)
408
+ - **n8n Version**: 2.17.2+ (tested with latest)
380
409
 
381
410
  - **Node Version**: 20+
382
411
 
@@ -36,7 +36,11 @@ export declare class LearningSuite implements INodeType {
36
36
  hub_getTemplates(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
37
37
  group_getGroups(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
38
38
  customFields_getCards(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
39
- customFields_getDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
39
+ customFields_getDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<{
40
+ name: string;
41
+ value: string;
42
+ }[]>;
43
+ customFields_getMediaDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
40
44
  customFields_getCategories(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
41
45
  customFields_getFieldType(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<{
42
46
  name: string;
@@ -55,6 +59,8 @@ export declare class LearningSuite implements INodeType {
55
59
  community_getBadges(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
56
60
  community_getLatestPosts(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
57
61
  bundle_getBundles(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
62
+ ai_getAgentActions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
63
+ ai_getAiAgents(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
58
64
  };
59
65
  resourceMapping: {
60
66
  getTemplateVariablesResourceMapperFields: typeof getTemplateVariablesResourceMapperFields;
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.LearningSuite = void 0;
37
37
  const n8n_workflow_1 = require("n8n-workflow");
38
38
  // methods - loadOptions
39
+ const loAi = __importStar(require("./methods/loadOptions/ai.loadOptions"));
39
40
  const loBundle = __importStar(require("./methods/loadOptions/bundle.loadOptions"));
40
41
  const loCommunity = __importStar(require("./methods/loadOptions/community.loadOptions"));
41
42
  const loCourse = __importStar(require("./methods/loadOptions/course.loadOptions"));
@@ -150,6 +151,7 @@ class LearningSuite {
150
151
  };
151
152
  this.methods = {
152
153
  loadOptions: {
154
+ ...loAi,
153
155
  ...loBundle,
154
156
  ...loCommunity,
155
157
  ...loCourse,
@@ -4,7 +4,11 @@ export declare class LearningSuiteTrigger implements INodeType {
4
4
  methods: {
5
5
  loadOptions: {
6
6
  customFields_getCards(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
7
- customFields_getDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
7
+ customFields_getDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<{
8
+ name: string;
9
+ value: string;
10
+ }[]>;
11
+ customFields_getMediaDefinitions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
8
12
  customFields_getCategories(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
9
13
  customFields_getFieldType(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<{
10
14
  name: string;
@@ -53,6 +57,8 @@ export declare class LearningSuiteTrigger implements INodeType {
53
57
  community_getBadges(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
54
58
  community_getLatestPosts(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
55
59
  bundle_getBundles(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
60
+ ai_getAgentActions(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
61
+ ai_getAiAgents(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodePropertyOptions[]>;
56
62
  };
57
63
  };
58
64
  webhookMethods: {
@@ -39,6 +39,7 @@ const request_1 = require("./shared/request");
39
39
  const trigger_instant_properties_1 = require("./descriptions/trigger.instant.properties");
40
40
  const parsing_1 = require("./shared/parsing");
41
41
  // methods - loadOptions
42
+ const loAi = __importStar(require("./methods/loadOptions/ai.loadOptions"));
42
43
  const loBundle = __importStar(require("./methods/loadOptions/bundle.loadOptions"));
43
44
  const loCommunity = __importStar(require("./methods/loadOptions/community.loadOptions"));
44
45
  const loCourse = __importStar(require("./methods/loadOptions/course.loadOptions"));
@@ -52,6 +53,7 @@ const loWebhook = __importStar(require("./methods/loadOptions/webhook.loadOption
52
53
  const loTeamMember = __importStar(require("./methods/loadOptions/teamMember.loadOptions"));
53
54
  const loCustomFields = __importStar(require("./methods/loadOptions/customFields.loadOptions"));
54
55
  const INSTANT_EVENTS = new Set([
56
+ 'agentAction.executed',
55
57
  'accessRequest.created',
56
58
  'communityPost.created',
57
59
  'communityPost.commented',
@@ -101,6 +103,17 @@ function buildDesiredFilter(event) {
101
103
  }
102
104
  };
103
105
  switch (event) {
106
+ // ---------------- Agent Action
107
+ case 'agentAction.executed': {
108
+ const col = getCol('additionalAgentActionExecuted');
109
+ if (col === null || col === void 0 ? void 0 : col.toolKey) {
110
+ filter.toolKey = String(col.toolKey);
111
+ }
112
+ if (col === null || col === void 0 ? void 0 : col.agentId) {
113
+ filter.agentId = String(col.agentId);
114
+ }
115
+ break;
116
+ }
104
117
  // ---------------- Community
105
118
  case 'communityPost.commented': {
106
119
  const col = getCol('additionalCommunityPostCommented');
@@ -290,6 +303,7 @@ class LearningSuiteTrigger {
290
303
  };
291
304
  this.methods = {
292
305
  loadOptions: {
306
+ ...loAi,
293
307
  ...loBundle,
294
308
  ...loCommunity,
295
309
  ...loCourse,
@@ -10,6 +10,24 @@ exports.aiProperties = [
10
10
  default: 'ragChat',
11
11
  displayOptions: { show: { resource: ['ai'] } },
12
12
  options: [
13
+ {
14
+ name: 'Agent Chat',
15
+ value: 'agentChat',
16
+ description: 'Send a message to an AI agent and get the response',
17
+ action: 'Send message to AI agent',
18
+ },
19
+ {
20
+ name: 'Get Agent Actions',
21
+ value: 'getAgentActions',
22
+ description: 'List all agent actions',
23
+ action: 'List agent actions',
24
+ },
25
+ {
26
+ name: 'Get AI Agents',
27
+ value: 'getAiAgents',
28
+ description: 'List all enabled AI agents',
29
+ action: 'List AI agents',
30
+ },
13
31
  {
14
32
  name: 'RAG Chat',
15
33
  value: 'ragChat',
@@ -18,6 +36,74 @@ exports.aiProperties = [
18
36
  },
19
37
  ],
20
38
  },
39
+ {
40
+ displayName: 'AI Agent Name or ID',
41
+ name: 'agentId',
42
+ type: 'options',
43
+ typeOptions: { loadOptionsMethod: 'ai_getAiAgents' },
44
+ required: true,
45
+ default: '',
46
+ description: 'The AI agent to chat with. For the global AI Concierge agent, you may also use the shortcut "concierge". Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
47
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
48
+ },
49
+ {
50
+ displayName: 'User Name or ID',
51
+ name: 'userId',
52
+ type: 'options',
53
+ typeOptions: { loadOptionsMethod: 'member_getMembers' },
54
+ required: true,
55
+ default: '',
56
+ description: 'The user ID of the member sending the message. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
57
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
58
+ },
59
+ {
60
+ displayName: 'Message',
61
+ name: 'message',
62
+ type: 'string',
63
+ default: '',
64
+ description: 'The message you want to send to the AI agent',
65
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
66
+ },
67
+ {
68
+ displayName: 'Chat ID',
69
+ name: 'chatId',
70
+ type: 'string',
71
+ default: '',
72
+ description: 'The chat/conversation you want to send the message to. Leave empty to start a new chat.',
73
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
74
+ },
75
+ {
76
+ displayName: 'Include Chat History',
77
+ name: 'includeChatHistory',
78
+ type: 'boolean',
79
+ default: false,
80
+ description: 'Whether to return the full chat history in the response. Otherwise, only the latest agent response is returned.',
81
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
82
+ },
83
+ {
84
+ displayName: 'End Chat',
85
+ name: 'endChat',
86
+ type: 'boolean',
87
+ default: false,
88
+ description: 'Whether to end the chat after this message. The agent will not generate a response. Useful when filling out a form is complete.',
89
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
90
+ },
91
+ {
92
+ displayName: 'Metadata',
93
+ name: 'metadata',
94
+ type: 'json',
95
+ default: '{}',
96
+ description: 'If a previous agent response included metadata, it should be included in the next request. Provide as JSON object.',
97
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
98
+ },
99
+ {
100
+ displayName: 'Profile Context',
101
+ name: 'profileContext',
102
+ type: 'json',
103
+ default: '{}',
104
+ description: 'Optional profile context to use when interacting with custom field (forms). Only used if the agent config supports it. Provide as JSON object with a "selectedProfileIdByCard" property.',
105
+ displayOptions: { show: { resource: ['ai'], operation: ['agentChat'] } },
106
+ },
21
107
  {
22
108
  displayName: 'Question',
23
109
  name: 'question',
@@ -88,6 +88,12 @@ exports.customFieldsProperties = [
88
88
  description: 'Update a custom field value within a profile of a custom field card',
89
89
  action: 'Update a custom field value within a profile of a custom field card',
90
90
  },
91
+ {
92
+ name: 'Upload File From URL',
93
+ value: 'createFileUploadTarget',
94
+ description: 'Upload a file from a public URL and append it to a custom field',
95
+ action: 'Upload a file from a public URL and append it to a custom field',
96
+ },
91
97
  ],
92
98
  },
93
99
  {
@@ -99,7 +105,7 @@ exports.customFieldsProperties = [
99
105
  },
100
106
  required: true,
101
107
  default: '',
102
- description: 'The ID of the user whose custom field data should be accessed. Choose from the list, or specify an ID using an expression. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
108
+ description: 'The ID of the user whose custom field data should be accessed. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
103
109
  displayOptions: {
104
110
  show: {
105
111
  resource: ['customFields'],
@@ -112,6 +118,7 @@ exports.customFieldsProperties = [
112
118
  'getStoreValues',
113
119
  'setFieldValue',
114
120
  'setMultipleFieldValues',
121
+ 'createFileUploadTarget',
115
122
  'updateProfileField',
116
123
  ],
117
124
  },
@@ -122,7 +129,7 @@ exports.customFieldsProperties = [
122
129
  name: 'customFieldCardId',
123
130
  type: 'options',
124
131
  default: '',
125
- description: 'Filter results by a specific custom field card. Choose from the list or specify an ID using an expression. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
132
+ description: 'Filter results by a specific custom field card. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
126
133
  typeOptions: {
127
134
  loadOptionsMethod: 'customFields_getCards',
128
135
  },
@@ -139,7 +146,7 @@ exports.customFieldsProperties = [
139
146
  type: 'options',
140
147
  required: true,
141
148
  default: '',
142
- description: 'The custom field card to use. Choose from the list or specify an ID using an expression. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
149
+ description: 'The custom field card to use. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
143
150
  typeOptions: {
144
151
  loadOptionsMethod: 'customFields_getCards',
145
152
  },
@@ -151,34 +158,41 @@ exports.customFieldsProperties = [
151
158
  },
152
159
  },
153
160
  {
154
- displayName: 'Profile Index',
155
- name: 'profileIndex',
156
- type: 'number',
157
- default: null,
158
- description: 'If specified, the profile with this index is used. Ignored if Profile ID is set. Takes precedence over Profile Name. If not specified or if the index does not exist for a given field key, the value in the default/first profile is returned.',
161
+ displayName: 'Profile ID',
162
+ name: 'profileId',
163
+ type: 'string',
164
+ default: '',
165
+ description: 'If specified, the profile with this ID is used. Takes precedence over Profile Index and Profile Name.',
159
166
  displayOptions: {
160
167
  show: {
161
168
  resource: ['customFields'],
162
169
  operation: [
163
170
  'setFieldValue',
164
- 'updateProfileField',
165
171
  'setMultipleFieldValues',
166
172
  'getProfileByCard',
167
- 'getStoreValues',
173
+ 'updateProfileField',
174
+ 'createFileUploadTarget',
168
175
  ],
169
176
  },
170
177
  },
171
178
  },
172
179
  {
173
- displayName: 'Profile ID',
174
- name: 'profileId',
175
- type: 'string',
176
- default: '',
177
- description: 'If specified, the profile with this ID is used. Takes precedence over Profile Index and Profile Name.',
180
+ displayName: 'Profile Index',
181
+ name: 'profileIndex',
182
+ type: 'number',
183
+ default: null,
184
+ description: 'If specified, the profile with this index is used. Ignored if Profile ID is set. Takes precedence over Profile Name. If not specified or if the index does not exist for a given field key, the value in the default/first profile is returned.',
178
185
  displayOptions: {
179
186
  show: {
180
187
  resource: ['customFields'],
181
- operation: ['setFieldValue', 'setMultipleFieldValues', 'getProfileByCard', 'updateProfileField'],
188
+ operation: [
189
+ 'setFieldValue',
190
+ 'updateProfileField',
191
+ 'setMultipleFieldValues',
192
+ 'createFileUploadTarget',
193
+ 'getProfileByCard',
194
+ 'getStoreValues',
195
+ ],
182
196
  },
183
197
  },
184
198
  },
@@ -191,7 +205,7 @@ exports.customFieldsProperties = [
191
205
  displayOptions: {
192
206
  show: {
193
207
  resource: ['customFields'],
194
- operation: ['updateProfileField', 'getProfileByCard'],
208
+ operation: ['updateProfileField', 'getProfileByCard', 'createFileUploadTarget'],
195
209
  },
196
210
  },
197
211
  },
@@ -213,6 +227,52 @@ exports.customFieldsProperties = [
213
227
  },
214
228
  default: '',
215
229
  },
230
+ {
231
+ displayName: 'Field Key Name or ID',
232
+ name: 'customFieldKey',
233
+ type: 'options',
234
+ description: 'The file, image, video, or audio custom field to append to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
235
+ required: true,
236
+ typeOptions: {
237
+ loadOptionsMethod: 'customFields_getMediaDefinitions',
238
+ },
239
+ displayOptions: {
240
+ show: {
241
+ resource: ['customFields'],
242
+ operation: ['createFileUploadTarget'],
243
+ },
244
+ },
245
+ default: '',
246
+ },
247
+ {
248
+ displayName: 'File Name',
249
+ name: 'customFieldFileName',
250
+ type: 'string',
251
+ default: '',
252
+ placeholder: 'e.g. report.pdf',
253
+ description: 'Optional title for videos. Also used for files in the custom field file value returned by LearningSuite.',
254
+ displayOptions: {
255
+ show: {
256
+ resource: ['customFields'],
257
+ operation: ['createFileUploadTarget'],
258
+ },
259
+ },
260
+ },
261
+ {
262
+ displayName: 'Public Download URL',
263
+ name: 'publicDownloadUrl',
264
+ type: 'string',
265
+ default: '',
266
+ required: true,
267
+ placeholder: 'https://example.com/file.pdf',
268
+ description: 'Public URL that LearningSuite downloads and uploads before returning the custom field file value',
269
+ displayOptions: {
270
+ show: {
271
+ resource: ['customFields'],
272
+ operation: ['createFileUploadTarget'],
273
+ },
274
+ },
275
+ },
216
276
  {
217
277
  displayName: 'Field Type Name or ID',
218
278
  name: 'fieldType',
@@ -348,6 +408,67 @@ exports.customFieldsProperties = [
348
408
  },
349
409
  },
350
410
  },
411
+ {
412
+ displayName: 'File Value Mode',
413
+ name: 'fileValueMode',
414
+ type: 'options',
415
+ default: 'add',
416
+ description: 'How to handle existing file values in the custom field',
417
+ options: [
418
+ {
419
+ name: 'Add',
420
+ value: 'add',
421
+ description: 'Append uploaded files and fail if the field limit would be exceeded',
422
+ },
423
+ {
424
+ name: 'Replace',
425
+ value: 'replace',
426
+ description: 'Replace all existing file values with the uploaded files',
427
+ },
428
+ {
429
+ name: 'Replace if Limit Reached',
430
+ value: 'replaceIfFull',
431
+ description: 'Append uploaded files, but replace existing files if the field limit would be exceeded',
432
+ },
433
+ ],
434
+ displayOptions: {
435
+ show: {
436
+ resource: ['customFields'],
437
+ operation: ['setFieldValue', 'updateProfileField'],
438
+ fieldType: ['files', 'images', 'videos', 'audios'],
439
+ },
440
+ },
441
+ },
442
+ {
443
+ displayName: 'File Value Mode',
444
+ name: 'fileValueMode',
445
+ type: 'options',
446
+ default: 'add',
447
+ description: 'How to handle existing file values in the custom field',
448
+ options: [
449
+ {
450
+ name: 'Add',
451
+ value: 'add',
452
+ description: 'Append uploaded files and fail if the field limit would be exceeded',
453
+ },
454
+ {
455
+ name: 'Replace',
456
+ value: 'replace',
457
+ description: 'Replace all existing file values with the uploaded files',
458
+ },
459
+ {
460
+ name: 'Replace if Limit Reached',
461
+ value: 'replaceIfFull',
462
+ description: 'Append uploaded files, but replace existing files if the field limit would be exceeded',
463
+ },
464
+ ],
465
+ displayOptions: {
466
+ show: {
467
+ resource: ['customFields'],
468
+ operation: ['setMultipleFieldValues', 'createFileUploadTarget'],
469
+ },
470
+ },
471
+ },
351
472
  {
352
473
  displayName: 'File Name',
353
474
  name: 'fieldValueFileName',
@@ -10,6 +10,11 @@ exports.instantProperties = [
10
10
  default: 'communityPost.created',
11
11
  description: 'Select the LearningSuite instant (webhook) event',
12
12
  options: [
13
+ {
14
+ name: 'Agent Action Executed',
15
+ value: 'agentAction.executed',
16
+ description: 'Triggers when an AI agent action has been executed',
17
+ },
13
18
  {
14
19
  name: 'Community Post Commented',
15
20
  value: 'communityPost.commented',
@@ -89,6 +94,33 @@ exports.instantProperties = [
89
94
  },
90
95
  ],
91
96
  },
97
+ // Agent Action Executed
98
+ {
99
+ displayName: 'Agent Action Executed Options',
100
+ name: 'additionalAgentActionExecuted',
101
+ type: 'collection',
102
+ default: {},
103
+ placeholder: 'Add option',
104
+ displayOptions: { show: { event: ['agentAction.executed'] } },
105
+ options: [
106
+ {
107
+ displayName: 'Tool Key Name or ID',
108
+ name: 'toolKey',
109
+ type: 'options',
110
+ default: '',
111
+ description: 'Optional: Only trigger for a specific agent action. Leave empty to trigger for all actions. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
112
+ typeOptions: { loadOptionsMethod: 'ai_getAgentActions' },
113
+ },
114
+ {
115
+ displayName: 'Agent Name or ID',
116
+ name: 'agentId',
117
+ type: 'options',
118
+ default: '',
119
+ description: 'Optional: Only trigger for actions executed by a specific AI agent. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
120
+ typeOptions: { loadOptionsMethod: 'ai_getAiAgents' },
121
+ },
122
+ ],
123
+ },
92
124
  // New Login
93
125
  {
94
126
  displayName: 'Login Options',
@@ -80,6 +80,7 @@ exports.webhookProperties = [
80
80
  displayOptions: { show: { resource: ['webhook'], operation: ['createSubscription', 'updateSubscription'] } },
81
81
  description: 'Type of event to subscribe to',
82
82
  options: [
83
+ { name: 'Agent Action Executed', value: 'agentAction.executed' },
83
84
  { name: 'Community Post Commented', value: 'communityPost.commented' },
84
85
  { name: 'Community Post Created', value: 'communityPost.created' },
85
86
  { name: 'Community Post Moderated', value: 'communityPost.moderated' },
@@ -109,6 +110,7 @@ exports.webhookProperties = [
109
110
  required: true,
110
111
  description: 'Type of sample data to retrieve',
111
112
  options: [
113
+ { name: 'Agent Action Executed Events', value: 'agent-action-executed-events' },
112
114
  { name: 'Community Post Commented', value: 'community-post-commented-events' },
113
115
  { name: 'Community Post Created Events', value: 'community-post-created-events' },
114
116
  { name: 'Community Post Moderated Events', value: 'community-post-moderated-events' },
@@ -127,6 +129,39 @@ exports.webhookProperties = [
127
129
  ],
128
130
  },
129
131
  // ====== Options per event (identical to instantProperties) ======
132
+ // Agent Action Executed
133
+ {
134
+ displayName: 'Agent Action Executed Options',
135
+ name: 'additionalAgentActionExecuted',
136
+ type: 'collection',
137
+ default: {},
138
+ placeholder: 'Add option',
139
+ displayOptions: {
140
+ show: {
141
+ resource: ['webhook'],
142
+ operation: ['createSubscription', 'updateSubscription'],
143
+ eventType: ['agentAction.executed'],
144
+ },
145
+ },
146
+ options: [
147
+ {
148
+ displayName: 'Tool Key Name or ID',
149
+ name: 'toolKey',
150
+ type: 'options',
151
+ default: '',
152
+ description: 'Optional: Only trigger for a specific agent action. Leave empty to trigger for all actions. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
153
+ typeOptions: { loadOptionsMethod: 'ai_getAgentActions' },
154
+ },
155
+ {
156
+ displayName: 'Agent Name or ID',
157
+ name: 'agentId',
158
+ type: 'options',
159
+ default: '',
160
+ description: 'Optional: Only trigger for actions executed by a specific AI agent. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
161
+ typeOptions: { loadOptionsMethod: 'ai_getAiAgents' },
162
+ },
163
+ ],
164
+ },
130
165
  // Login Options
131
166
  {
132
167
  displayName: 'Login Options',