@kumologica/sdk 3.4.0 → 3.5.0-beta2

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 (51) hide show
  1. package/cli/commands/create-commands/openapi.js +42 -0
  2. package/cli/commands/create.js +17 -8
  3. package/cli/commands/login.js +87 -0
  4. package/package.json +18 -7
  5. package/src/app/lib/ai/layout.js +75 -0
  6. package/src/app/lib/ai/openai.js +108 -0
  7. package/src/app/lib/ai/prompt.txt +583 -0
  8. package/src/app/lib/aws/ca-cloudwatch-api.js +2 -10
  9. package/src/app/lib/aws/ca-dynamodb-api.js +6 -10
  10. package/src/app/lib/aws/ca-elb-api.js +4 -24
  11. package/src/app/lib/aws/ca-events-api.js +5 -12
  12. package/src/app/lib/aws/ca-iot-api.js +3 -87
  13. package/src/app/lib/aws/ca-s3-api.js +17 -62
  14. package/src/app/lib/aws/ca-sns-api.js +6 -15
  15. package/src/app/lib/aws/ca-sqs-api.js +9 -6
  16. package/src/app/lib/aws/index.js +70 -86
  17. package/src/app/lib/aws/kl-apigw-api.js +40 -0
  18. package/src/app/lib/aws/kl-iam-api.js +5 -5
  19. package/src/app/lib/github/index.js +0 -17
  20. package/src/app/lib/serverless/index.js +1 -1
  21. package/src/app/lib/stores/settings-cloud-store.js +35 -2
  22. package/src/app/main.js +34 -32
  23. package/src/app/preload.js +36 -28
  24. package/src/app/ui/editor-client/public/red/red.js +924 -458
  25. package/src/app/ui/editor-client/public/red/red.min.js +2 -2
  26. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  27. package/src/app/ui/editor-client/src/js/nodes.js +19 -18
  28. package/src/app/ui/editor-client/src/js/red.js +6 -3
  29. package/src/app/ui/editor-client/src/js/ui/editor.js +70 -70
  30. package/src/app/ui/editor-client/src/js/ui/footer.js +143 -0
  31. package/src/app/ui/editor-client/src/js/ui/search.js +43 -34
  32. package/src/app/ui/editor-client/src/js/ui/sidebar.js +26 -24
  33. package/src/app/ui/editor-client/src/js/ui/signup.js +56 -0
  34. package/src/app/ui/editor-client/src/js/ui/tab-ai.js +210 -0
  35. package/src/app/ui/editor-client/src/js/ui/tab-awsDeploy.js +30 -5
  36. package/src/app/ui/editor-client/src/js/ui/tab-test.js +120 -99
  37. package/src/app/ui/editor-client/src/js/ui/update-panel.js +0 -1
  38. package/src/app/ui/editor-client/src/js/ui/view.js +201 -202
  39. package/src/app/ui/editor-client/src/sass/editor.scss +715 -645
  40. package/src/app/ui/editor-client/src/sass/sidebar.scss +21 -12
  41. package/src/app/ui/editor-client/src/sass/style.scss +101 -0
  42. package/src/app/ui/editor-client/src/sass/tab-ai.scss +68 -0
  43. package/src/app/ui/editor-client/src/sass/workspace.scss +12 -2
  44. package/src/app/ui/editor-client/templates/index.mst +41 -7
  45. package/src/server/DesignerServer.js +2 -1
  46. package/cli/.DS_Store +0 -0
  47. package/fixtures/.DS_Store +0 -0
  48. package/src/app/lib/aws/ca-apigw-api.js +0 -216
  49. package/src/app/lib/aws/ca-codecommit-api.js +0 -63
  50. package/src/app/lib/aws/kl-rekognition-api.js +0 -66
  51. package/src/app/lib/aws/kl-ssm-api.js +0 -24
@@ -90,16 +90,16 @@ RED.search = (function () {
90
90
  }
91
91
  } else {
92
92
  let commands = searchCommands();
93
- commands.forEach(c=> {
93
+ commands.forEach(c => {
94
94
  searchResults.editableList('addItem', c);
95
95
  });
96
96
 
97
97
  let results = $('#search-result-list');
98
98
  $('<div class="searchSeparator"></div>').appendTo(results);
99
99
 
100
-
100
+
101
101
  let allNodes = searchNodes();
102
-
102
+
103
103
  allNodes.forEach(n => {
104
104
  searchResults.editableList('addItem', n);
105
105
  })
@@ -107,7 +107,7 @@ RED.search = (function () {
107
107
  }
108
108
  }
109
109
 
110
- function searchNodes(val, typeFilter){
110
+ function searchNodes(val, typeFilter) {
111
111
  results = [];
112
112
  if (val) {
113
113
  val = val.trim();
@@ -148,10 +148,10 @@ RED.search = (function () {
148
148
  if (setResults.has(n.node.id)) return;
149
149
  else {
150
150
  setResults.add(n.node.id);
151
- if (n.node.type === 'tab'){
152
- results.push({ label:n.node.label, node: n.node});
153
- }else {
154
- results.push({ label:n.node.name, node: n.node});
151
+ if (n.node.type === 'tab') {
152
+ results.push({ label: n.node.label, node: n.node });
153
+ } else {
154
+ results.push({ label: n.node.name, node: n.node });
155
155
  }
156
156
  }
157
157
  })
@@ -165,30 +165,37 @@ RED.search = (function () {
165
165
  * Returns a list of commands that will be added to the search window when it is opened
166
166
  */
167
167
  function searchCommands() {
168
+
168
169
  return [
169
170
  { type: 'command', title: 'Open Settings', action: 'core:settings:open', shortcut: `${CtrlOrCmd()} /` },
170
171
  { type: 'command', title: 'Show Project Info', action: 'core:project-info' },
171
- { type: 'command', title: 'Run Test...', cb: () => {
172
- if (!$('.sidebar-test').is(':visible')){
173
- $('#red-ui-tab-test-link-button').click();
172
+ {
173
+ type: 'command', title: 'Run Test...', cb: () => {
174
+ if (!$('.sidebar-test').is(':visible')) {
175
+ $('#red-ui-tab-test-link-button').click();
176
+ }
177
+
178
+ $('#test-sidebar-run-btn').click();
174
179
  }
175
-
176
- $('#test-sidebar-run-btn').click();
177
- } },
178
- { type: 'command', title: 'Open Log Viewer', cb: ()=> {
179
- $('#workspace-terminal').toggle()
180
- }, shortcut: `${CtrlOrCmd()} T` },
180
+ },
181
+ {
182
+ type: 'command', title: 'Open Log Viewer', cb: () => {
183
+ $('#workspace-terminal').toggle()
184
+ }, shortcut: `${CtrlOrCmd()} T`
185
+ },
181
186
  { type: 'command', title: 'Import Flow', action: 'core:show-import-dialog', shortcut: `${CtrlOrCmd()} I` },
182
187
  { type: 'command', title: 'Export Flow', action: 'core:show-export-dialog', shortcut: `${CtrlOrCmd()} E` },
183
- { type: 'command', title: 'Help: Documentation', cb: ()=> {
188
+ // { type: 'command', title: 'SignIn to Kumologica.dev', action: 'core:signup:show' },
189
+ {
190
+ type: 'command', title: 'Help: Documentation', cb: () => {
184
191
  window.__kumologica.electron.shell.openExternal('https://docs.kumologica.com/docs/guide/Intro.html');
185
- },
192
+ }
186
193
  }
187
194
  ]
188
195
  }
189
196
 
190
197
  function CtrlOrCmd() {
191
- return window.__kumologica.settings.platform.isMac? "⌘": "Ctrl";
198
+ return window.__kumologica.settings.platform.isMac ? "⌘" : "Ctrl";
192
199
  }
193
200
 
194
201
  function ensureSelectedIsVisible() {
@@ -284,7 +291,7 @@ RED.search = (function () {
284
291
  // If node === undefiend and object is empty => user search yield no results
285
292
  // otherwise is a normal search ...
286
293
 
287
- if (node === undefined && !object ) {
294
+ if (node === undefined && !object) {
288
295
  // case of user search yield no results
289
296
  $('<div>', { class: 'red-ui-search-empty' })
290
297
  .text('No matches found')
@@ -305,8 +312,8 @@ RED.search = (function () {
305
312
  }).appendTo(div);
306
313
 
307
314
  $('<div>', { class: 'red-ui-search-result-command-label', style: 'width:95%' })
308
- .text(object.title)
309
- .appendTo(contentDescription);
315
+ .text(object.title)
316
+ .appendTo(contentDescription);
310
317
 
311
318
  // Type of object (command)
312
319
  $('<div>', { class: 'red-ui-search-result-command-shortcut' })
@@ -315,16 +322,18 @@ RED.search = (function () {
315
322
 
316
323
  div.click(function (evt) {
317
324
  evt.preventDefault();
318
- if (object.action){
325
+ if (object.action) {
319
326
  hide();
320
- window.setTimeout( ()=> {
321
- RED.actions.invoke(object.action)}, 10)
327
+ window.setTimeout(() => {
328
+ RED.actions.invoke(object.action)
329
+ }, 10)
322
330
  } else {
323
331
  hide();
324
- window.setTimeout( ()=> {
325
- object.cb() }, 10)
332
+ window.setTimeout(() => {
333
+ object.cb()
334
+ }, 10)
326
335
  }
327
-
336
+
328
337
  });
329
338
  }
330
339
 
@@ -347,7 +356,7 @@ RED.search = (function () {
347
356
 
348
357
  var colour = RED.utils.getNodeColor(node.type, def);
349
358
  var icon_url = RED.utils.getNodeIcon(def, node);
350
-
359
+
351
360
  if (node.type === 'tab') {
352
361
  var iconContainer = $('<div/>', {
353
362
  class: 'palette_icon_container',
@@ -399,7 +408,7 @@ RED.search = (function () {
399
408
  RED.view.reveal(node.id);
400
409
  }
401
410
 
402
- function revealByNodeId(nodeId){
411
+ function revealByNodeId(nodeId) {
403
412
  var selectedNode = RED.nodes.node(nodeId);
404
413
  reveal(selectedNode);
405
414
  }
@@ -427,15 +436,15 @@ RED.search = (function () {
427
436
  searchInput.searchBox('value', v);
428
437
  RED.events.emit('search:open');
429
438
  visible = true;
430
- window.setTimeout(()=> {
431
- searchInput.focus()
439
+ window.setTimeout(() => {
440
+ searchInput.focus()
432
441
  }, 50);
433
442
 
434
443
  // Populate search results with commands and tabs at least
435
444
  search();
436
445
  }
437
446
 
438
-
447
+
439
448
  }
440
449
 
441
450
  function hide() {
@@ -19,9 +19,9 @@ RED.sidebar = (function () {
19
19
  $(tab.toolbar).show();
20
20
  }
21
21
  }
22
-
22
+
23
23
  },
24
- onsame: function (tab){
24
+ onsame: function (tab) {
25
25
  if (tab.onsame) {
26
26
  tab.onsame.call(tab);
27
27
  }
@@ -126,16 +126,16 @@ RED.sidebar = (function () {
126
126
  let d = ui.position.left;
127
127
  delta = sidebarWidthP0 - d;
128
128
  $('#sidebar').width(delta);
129
- if ($('#sidebar').width() > maxWidthSidebar()){
129
+ if ($('#sidebar').width() > maxWidthSidebar()) {
130
130
  $('#sidebar').width(maxWidthSidebar());
131
131
  }
132
132
  event.stopImmediatePropagation();
133
133
  RED.events.emit('sidebar:resize');
134
134
  },
135
135
  stop: function (event, ui) {
136
- setTimeout(function() {
136
+ setTimeout(function () {
137
137
  sidebarDragging = false;
138
- },1000);
138
+ }, 1000);
139
139
  RED.events.emit('sidebar:resize');
140
140
  },
141
141
  });
@@ -159,10 +159,10 @@ RED.sidebar = (function () {
159
159
  return totalWidth - shortcutsWidth - paletteWidth - sidebarSeparatorWidth;
160
160
  }
161
161
 
162
- function maximizeSidebar(){
162
+ function maximizeSidebar() {
163
163
  const targetWidth = maxWidthSidebar();
164
164
  $('#sidebar').width(targetWidth);
165
-
165
+
166
166
  // Hack: Make sure the workspace if reset before maximizing the sidebar. This is because when dragging the sidebar the workspace width is also modified
167
167
  $('#workspace').css('right', 485);
168
168
  RED.events.emit('sidebar:resize');
@@ -177,7 +177,7 @@ RED.sidebar = (function () {
177
177
  }
178
178
 
179
179
  function isSidebarVisible() {
180
- return ! $('#main-container').hasClass('sidebar-closed');
180
+ return !$('#main-container').hasClass('sidebar-closed');
181
181
  }
182
182
 
183
183
  function toggleSidebar(state) {
@@ -188,7 +188,7 @@ RED.sidebar = (function () {
188
188
  $('#main-container').addClass('sidebar-closed');
189
189
  $('#shelve-right').removeClass('shelf-selected');
190
190
  } else {
191
- if (!$('#shelve-right').hasClass('shelf-selected')){
191
+ if (!$('#shelve-right').hasClass('shelf-selected')) {
192
192
  checkIfscrollWorkspaceRequired = true;
193
193
  }
194
194
  // Show the sidebar and sidebar-separator
@@ -198,7 +198,7 @@ RED.sidebar = (function () {
198
198
  sidebar_tabs.resize();
199
199
  }
200
200
  RED.events.emit('sidebar:resize');
201
- if (checkIfscrollWorkspaceRequired && RED.editor.getLatestNodeSelected()){
201
+ if (checkIfscrollWorkspaceRequired && RED.editor.getLatestNodeSelected()) {
202
202
  // Reposition the workspace if the node may be left hidden behind the sidebar
203
203
  const safeDistNodeSidebar = 300;
204
204
  let nodeSelectedPosX = RED.editor.getLatestNodeSelected().x;
@@ -210,9 +210,9 @@ RED.sidebar = (function () {
210
210
  // - sidebarPosLeftX: ${sidebarPosLeftX}
211
211
  // ----------------------------------------
212
212
  // `);
213
- if (nodeSelectedPosX - initialScrollLeft + safeDistNodeSidebar > sidebarPosLeftX ){
214
- let targetScrollLeft = nodeSelectedPosX - sidebarPosLeftX + safeDistNodeSidebar;
215
- $('#chart').animate( { scrollLeft: targetScrollLeft})
213
+ if (nodeSelectedPosX - initialScrollLeft + safeDistNodeSidebar > sidebarPosLeftX) {
214
+ let targetScrollLeft = nodeSelectedPosX - sidebarPosLeftX + safeDistNodeSidebar;
215
+ $('#chart').animate({ scrollLeft: targetScrollLeft })
216
216
  }
217
217
  }
218
218
  }
@@ -234,7 +234,7 @@ RED.sidebar = (function () {
234
234
  return sidebar_tabs.contains(id);
235
235
  }
236
236
 
237
- function deselectAll(){
237
+ function deselectAll() {
238
238
  // Deselect the shortcut icon
239
239
  let selectedTab = $('.sidebar-shortcuts-icons').find('a.active');
240
240
  selectedTab.each(function () {
@@ -252,11 +252,11 @@ RED.sidebar = (function () {
252
252
 
253
253
  }
254
254
 
255
- function selectTab(index){
255
+ function selectTab(index) {
256
256
  let selectedTab = $('#sidebar-shortcuts').find('.sidebar-shortcuts-icons').children()[index];
257
257
  // Click only if has not been selected
258
258
  // console.log('[sidebar] selectedTab.hasClass(selected)=', selectedTab.hasClass('selected'));
259
- if (!$(selectedTab).hasClass('selected')){
259
+ if (!$(selectedTab).hasClass('selected')) {
260
260
  $(selectedTab).click();
261
261
  }
262
262
  }
@@ -270,29 +270,29 @@ RED.sidebar = (function () {
270
270
  }
271
271
  });
272
272
 
273
- RED.actions.add('core:show-sidebar', function(e){
273
+ RED.actions.add('core:show-sidebar', function (e) {
274
274
  //show the sidebar
275
275
  toggleSidebar(true);
276
276
 
277
277
  //show the sidebar-separator
278
278
  // let sidebarSeparator = $('#sidebar-separator');
279
279
  // sidebarSeparator.show();
280
-
280
+
281
281
  // Select internally the tab
282
- if (e && e.hasOwnProperty('selectIndex')){
283
- selectTab(e.selectIndex);
282
+ if (e && e.hasOwnProperty('selectIndex')) {
283
+ selectTab(e.selectIndex);
284
284
  }
285
285
  });
286
286
 
287
- RED.actions.add('core:hide-sidebar', function(){
288
- if (!sidebarDragging){
287
+ RED.actions.add('core:hide-sidebar', function () {
288
+ if (!sidebarDragging) {
289
289
  toggleSidebar(false);
290
290
  deselectAll();
291
- }else {
291
+ } else {
292
292
  console.log('[sidebar] Ignoring hide-sidebar as dragging is still enabled')
293
293
  }
294
294
  });
295
-
295
+
296
296
  // RED.popover.tooltip(
297
297
  // $('#sidebar-separator').find('.sidebar-control-right'),
298
298
  // RED._('keyboard.toggleSidebar'),
@@ -309,6 +309,8 @@ RED.sidebar = (function () {
309
309
  RED.sidebar.azure.init();
310
310
  RED.sidebar.awsDeploy.init();
311
311
 
312
+ // RED.sidebar.ai.init();
313
+
312
314
 
313
315
 
314
316
  // hide info bar at start if screen rather narrow...
@@ -0,0 +1,56 @@
1
+ RED.signup = (function() {
2
+ // const {clipboard} = window.__kumologica.electron;
3
+
4
+ let signupWindow;
5
+ const url = "https://api.dev.kumologica.dev/signup/ui?x-api-key=MLTh1kkXBLaBefMHEFR3d6Svub0otStnaTjjsN5R";
6
+ //const url = "https://h5201rj4f8.execute-api.ap-southeast-2.amazonaws.com/default/signup/ui?x-api-key=MLTh1kkXBLaBefMHEFR3d6Svub0otStnaTjjsN5R";
7
+ function signupCompleted(details) {
8
+ const tokens = processCallback(details.url);
9
+ saveTokens(tokens);
10
+ signupWindow.destroy();
11
+ }
12
+
13
+ function processCallback(url) {
14
+ const u = url.replace("http://localhost:3000/#", "");
15
+ const t = u.split("&");
16
+ return t;
17
+ }
18
+
19
+ function saveTokens(tokens) {
20
+ const cfg = window.__kumologica.settings.settingsConfig;
21
+ cfg.saveKumologicaDevAlias(tokens);
22
+ }
23
+
24
+ function showSignup() {
25
+ const {BrowserWindow} = window.__kumologica.electron.remote;
26
+
27
+ signupWindow = new BrowserWindow({width:700, height:470});
28
+ signupWindow.loadURL(url);
29
+
30
+ const defaultSession = window.__kumologica.electron.remote.session.defaultSession;
31
+
32
+ defaultSession.webRequest.onBeforeRequest(
33
+ { urls: ["http://localhost:3000/*"] },
34
+ (details,
35
+ callback) => {
36
+ RED.events.emit('core:signup:completed', details);
37
+ });
38
+
39
+ signupWindow.on('authenticated', (a) => {
40
+ console.log("auth");
41
+ console.log(a);
42
+ });
43
+
44
+ signupWindow.on('closed', (a) => {
45
+ console.log("closed");
46
+ });
47
+ }
48
+
49
+ return {
50
+ init: function() {
51
+ RED.actions.add("core:signup:show", showSignup);
52
+ RED.events.on("core:signup:completed", (details) => signupCompleted(details));
53
+ },
54
+ // show: showSignup
55
+ }
56
+ })();
@@ -0,0 +1,210 @@
1
+ RED.sidebar.ai = (function () {
2
+ let tabContent;
3
+ let sections;
4
+ let stackContainer;
5
+ let latestCodeGenerated = '[]';
6
+
7
+ const INITIAL_MESSAGE = `Generate flow or node that ... (ctrl+enter to generate)`;
8
+
9
+ const openAIClient = window.__kumologica.libs.openAIClient; // TODO: javier
10
+
11
+ function initHTML() {
12
+ tabContent = document.createElement('div');
13
+ tabContent.className = 'sidebar-ai';
14
+ tabContent.style = "height: 100%";
15
+
16
+ RED.actions.add('core:show-ai-tab', show);
17
+
18
+ stackContainer = $('<div>', {
19
+ class: 'sidebar-node-info-stack',
20
+ style: 'height: 100%'
21
+ }).appendTo(tabContent);
22
+
23
+ // Append the header
24
+ let headerContentHtml = `
25
+ <div class="sidebar-ai-title-wrapper">
26
+ <div style="display:flex;flex-direction:column;padding-right:10px; width:100%; height: 100%">
27
+ <div id="sidebar-title-wrapper" style="display:flex">
28
+ <span>Generative AI</span>
29
+ </div>
30
+
31
+ <div id="sidebar-ai-body">
32
+ <div id="sidebar-ai-error-wrapper" style="display:none">
33
+ <span><b>An error occurred during processing your request</b>
34
+ <span>Please check the logs for additional details or contact support for assistance</span>
35
+ </div>
36
+ <div id="sidebar-ai-response-wrapper" style="display:none">
37
+ <div class="pt-0.5">
38
+ <div class="gizmo-shadow-stroke flex h-6 w-6 items-center justify-center overflow-hidden rounded-full">
39
+ <div class="relative p-1 rounded-sm h-9 w-9 text-white flex items-center justify-center" style="background-color: rgb(25, 195, 125); width: 24px; height: 24px; border-radius: 9999px; justify-content: center; align-items: center; color: white; margin-bottom: 7px">
40
+ <svg width="41" height="41" viewBox="0 0 41 41" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm" role="img"><text x="-9999" y="-9999">ChatGPT</text><path d="M37.5324 16.8707C37.9808 15.5241 38.1363 14.0974 37.9886 12.6859C37.8409 11.2744 37.3934 9.91076 36.676 8.68622C35.6126 6.83404 33.9882 5.3676 32.0373 4.4985C30.0864 3.62941 27.9098 3.40259 25.8215 3.85078C24.8796 2.7893 23.7219 1.94125 22.4257 1.36341C21.1295 0.785575 19.7249 0.491269 18.3058 0.500197C16.1708 0.495044 14.0893 1.16803 12.3614 2.42214C10.6335 3.67624 9.34853 5.44666 8.6917 7.47815C7.30085 7.76286 5.98686 8.3414 4.8377 9.17505C3.68854 10.0087 2.73073 11.0782 2.02839 12.312C0.956464 14.1591 0.498905 16.2988 0.721698 18.4228C0.944492 20.5467 1.83612 22.5449 3.268 24.1293C2.81966 25.4759 2.66413 26.9026 2.81182 28.3141C2.95951 29.7256 3.40701 31.0892 4.12437 32.3138C5.18791 34.1659 6.8123 35.6322 8.76321 36.5013C10.7141 37.3704 12.8907 37.5973 14.9789 37.1492C15.9208 38.2107 17.0786 39.0587 18.3747 39.6366C19.6709 40.2144 21.0755 40.5087 22.4946 40.4998C24.6307 40.5054 26.7133 39.8321 28.4418 38.5772C30.1704 37.3223 31.4556 35.5506 32.1119 33.5179C33.5027 33.2332 34.8167 32.6547 35.9659 31.821C37.115 30.9874 38.0728 29.9178 38.7752 28.684C39.8458 26.8371 40.3023 24.6979 40.0789 22.5748C39.8556 20.4517 38.9639 18.4544 37.5324 16.8707ZM22.4978 37.8849C20.7443 37.8874 19.0459 37.2733 17.6994 36.1501C17.7601 36.117 17.8666 36.0586 17.936 36.0161L25.9004 31.4156C26.1003 31.3019 26.2663 31.137 26.3813 30.9378C26.4964 30.7386 26.5563 30.5124 26.5549 30.2825V19.0542L29.9213 20.998C29.9389 21.0068 29.9541 21.0198 29.9656 21.0359C29.977 21.052 29.9842 21.0707 29.9867 21.0902V30.3889C29.9842 32.375 29.1946 34.2791 27.7909 35.6841C26.3872 37.0892 24.4838 37.8806 22.4978 37.8849ZM6.39227 31.0064C5.51397 29.4888 5.19742 27.7107 5.49804 25.9832C5.55718 26.0187 5.66048 26.0818 5.73461 26.1244L13.699 30.7248C13.8975 30.8408 14.1233 30.902 14.3532 30.902C14.583 30.902 14.8088 30.8408 15.0073 30.7248L24.731 25.1103V28.9979C24.7321 29.0177 24.7283 29.0376 24.7199 29.0556C24.7115 29.0736 24.6988 29.0893 24.6829 29.1012L16.6317 33.7497C14.9096 34.7416 12.8643 35.0097 10.9447 34.4954C9.02506 33.9811 7.38785 32.7263 6.39227 31.0064ZM4.29707 13.6194C5.17156 12.0998 6.55279 10.9364 8.19885 10.3327C8.19885 10.4013 8.19491 10.5228 8.19491 10.6071V19.808C8.19351 20.0378 8.25334 20.2638 8.36823 20.4629C8.48312 20.6619 8.64893 20.8267 8.84863 20.9404L18.5723 26.5542L15.206 28.4979C15.1894 28.5089 15.1703 28.5155 15.1505 28.5173C15.1307 28.5191 15.1107 28.516 15.0924 28.5082L7.04046 23.8557C5.32135 22.8601 4.06716 21.2235 3.55289 19.3046C3.03862 17.3858 3.30624 15.3413 4.29707 13.6194ZM31.955 20.0556L22.2312 14.4411L25.5976 12.4981C25.6142 12.4872 25.6333 12.4805 25.6531 12.4787C25.6729 12.4769 25.6928 12.4801 25.7111 12.4879L33.7631 17.1364C34.9967 17.849 36.0017 18.8982 36.6606 20.1613C37.3194 21.4244 37.6047 22.849 37.4832 24.2684C37.3617 25.6878 36.8382 27.0432 35.9743 28.1759C35.1103 29.3086 33.9415 30.1717 32.6047 30.6641C32.6047 30.5947 32.6047 30.4733 32.6047 30.3889V21.188C32.6066 20.9586 32.5474 20.7328 32.4332 20.5338C32.319 20.3348 32.154 20.1698 31.955 20.0556ZM35.3055 15.0128C35.2464 14.9765 35.1431 14.9142 35.069 14.8717L27.1045 10.2712C26.906 10.1554 26.6803 10.0943 26.4504 10.0943C26.2206 10.0943 25.9948 10.1554 25.7963 10.2712L16.0726 15.8858V11.9982C16.0715 11.9783 16.0753 11.9585 16.0837 11.9405C16.0921 11.9225 16.1048 11.9068 16.1207 11.8949L24.1719 7.25025C25.4053 6.53903 26.8158 6.19376 28.2383 6.25482C29.6608 6.31589 31.0364 6.78077 32.2044 7.59508C33.3723 8.40939 34.2842 9.53945 34.8334 10.8531C35.3826 12.1667 35.5464 13.6095 35.3055 15.0128ZM14.2424 21.9419L10.8752 19.9981C10.8576 19.9893 10.8423 19.9763 10.8309 19.9602C10.8195 19.9441 10.8122 19.9254 10.8098 19.9058V10.6071C10.8107 9.18295 11.2173 7.78848 11.9819 6.58696C12.7466 5.38544 13.8377 4.42659 15.1275 3.82264C16.4173 3.21869 17.8524 2.99464 19.2649 3.1767C20.6775 3.35876 22.0089 3.93941 23.1034 4.85067C23.0427 4.88379 22.937 4.94215 22.8668 4.98473L14.9024 9.58517C14.7025 9.69878 14.5366 9.86356 14.4215 10.0626C14.3065 10.2616 14.2466 10.4877 14.2479 10.7175L14.2424 21.9419ZM16.071 17.9991L20.4018 15.4978L24.7325 17.9975V22.9985L20.4018 25.4983L16.071 22.9985V17.9991Z" fill="currentColor"></path>
41
+ </svg>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ <div id="sidebar-ai-response-message">
46
+ <div id="sidebar-ai-response-action-wrapper">
47
+ <a id="sidebar-ai-import-flow" class="sidebar-header-button" href="#" style="margin-right:5px">
48
+ Import Flow
49
+ </a>
50
+ </div>
51
+ <span id="sidebar-ai-response-flow-value"></span>
52
+ </div>
53
+
54
+ </div>
55
+ </div>
56
+
57
+ <div id="sidebar-ai-prompt">
58
+ <div id="sidebar-ai-prompt-message-wrapper">
59
+ <textarea id="sidebar-ai-prompt-message" rows="4" placeholder="${INITIAL_MESSAGE}" style="min-height:130px"></textarea>
60
+ </div>
61
+ <div id="sidebar-ai-prompt-actions">
62
+ <a id="sidebar-ai-clear-btn" class="sidebar-header-button" href="#" style="margin-right:5px">
63
+ Clear
64
+ </a>
65
+ <a id="sidebar-ai-generate-btn" class="sidebar-header-button" href="#" style="color: white !important; background: #2979ff;">
66
+ Generate
67
+ </a>
68
+ </div>
69
+ <div id="sidebar-ai-prompt-noactions" style="display:none">
70
+ <a id="sidebar-ai-generating" class="sidebar-header-button" href="#" style="color: white !important; height: 24px;">
71
+ <img src="red/images/spin.svg" class="palette-spinner" style="height: 16px; width: 57px" />
72
+ </a>
73
+ </div>
74
+ </div>
75
+
76
+ <div id="ai-not-initialized" style="display:none">
77
+ <div style="display:flex; flex-direction: column; align-items: center; margin-top: 150px">
78
+ <div><i class="fa fa-magic" style="font-size: 56px; color: lightgrey;"></i></div>
79
+ <div style="font-weight: bold; font-size: 22px; margin-top: 15px;color: grey;">OpenAI API Key not found</div>
80
+ <div style="margin-top: 5px; color: grey;font-weight: 400; font-size: 13px;">To use this feature, you need to add your OpenAI key. </div>
81
+ <div style="margin-top: 10px"><span id="add-ai-key" style="font-weight: 500;font-size: 12px; color: #2979ff">Add key</span></div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ `;
87
+
88
+ $(headerContentHtml).appendTo(stackContainer);
89
+
90
+ RED.sidebar.addTab({
91
+ id: 'ai',
92
+ label: 'Gen AI',
93
+ name: 'Generative AI',
94
+ iconClass: 'fa fa-magic',
95
+ action: 'core:show-git-tab',
96
+ content: tabContent,
97
+ pinned: true,
98
+ enableOnEdit: true,
99
+ onchange: refreshTab,
100
+ onsame: onsame
101
+ })
102
+ }
103
+ function displayGeneratedCode(code) {
104
+ // update the latest code generated
105
+ latestCodeGenerated = JSON.stringify(code, null, 2);
106
+
107
+ $('#sidebar-ai-response-wrapper').show();
108
+ let $response = $('#sidebar-ai-response-flow-value');
109
+
110
+ RED.utils
111
+ .createObjectElement({ "code": code }, {
112
+ key: /*true*/ null,
113
+ typeHint: 'object',
114
+ hideKey: false,
115
+ path: '',
116
+ sourceId: 0,
117
+ rootPath: '',
118
+ })
119
+ .appendTo($response);
120
+ }
121
+
122
+ function changeStateToGenerating() {
123
+ latestCodeGenerated = '[]';
124
+ // Clear the previous response if required
125
+ $('#sidebar-ai-response-wrapper').hide();
126
+ $('#sidebar-ai-response-flow-value').empty();
127
+
128
+ // Control buttons
129
+ $('#sidebar-ai-prompt-actions').hide();
130
+ $('#sidebar-ai-prompt-noactions').show();
131
+ }
132
+
133
+ function changeStateToGenerated() {
134
+ $('#sidebar-ai-prompt-actions').show();
135
+ $('#sidebar-ai-prompt-noactions').hide();
136
+
137
+ }
138
+
139
+ function initJS() {
140
+ // Generate action
141
+ $('#sidebar-ai-generate-btn').click(async e => {
142
+ console.log('Asking AI to generate code...');
143
+ // Change the icon to loading
144
+ changeStateToGenerating();
145
+
146
+ let userPrompt = $('#sidebar-ai-prompt-message').val();
147
+ if (userPrompt) {
148
+ let response = await openAIClient.t2c(userPrompt);
149
+ displayGeneratedCode(response);
150
+ changeStateToGenerated();
151
+ } else {
152
+ changeStateToGenerated();
153
+ }
154
+
155
+
156
+ })
157
+ // Trigger generate action from ctrl+click
158
+ $('#sidebar-ai-prompt-message').keydown(e => {
159
+ if ((e.ctrlKey || e.metaKey) && (e.keyCode == 13 || e.keyCode == 10)) {
160
+ $('#sidebar-ai-generate-btn').click();
161
+ }
162
+ })
163
+
164
+ // Clear button
165
+ $('#sidebar-ai-clear-btn').click(async e => {
166
+ // Clear all messages
167
+ $('#sidebar-ai-response-wrapper').hide();
168
+ $('#sidebar-ai-response-flow-value').empty();
169
+
170
+ // Clear user prompt
171
+ $('#sidebar-ai-prompt-message').val('');
172
+ });
173
+
174
+ $('#sidebar-ai-import-flow').click(e => {
175
+ // Copy code to clipboard
176
+ const { clipboard } = window.__kumologica.electron;
177
+ clipboard.writeText(latestCodeGenerated);
178
+
179
+ // Open the import flow dialog
180
+ RED.actions.invoke('core:show-import-dialog')
181
+
182
+ // automatically trigger the import-from-clipboard option
183
+ setTimeout(() => { $('#import-from-clipboard').click() }, 100);
184
+ })
185
+ }
186
+
187
+ function init() {
188
+ initHTML();
189
+ initJS();
190
+ }
191
+
192
+ function show() {
193
+ RED.sidebar.show('ai');
194
+ }
195
+
196
+ function refreshTab(silently) {
197
+ if (!silently) {
198
+ RED.actions.invoke('core:show-sidebar');
199
+ }
200
+ }
201
+
202
+ function onsame() {
203
+ RED.actions.invoke('core:hide-sidebar');
204
+ }
205
+
206
+ return {
207
+ init: init,
208
+ show: show,
209
+ }
210
+ })();