@kumologica/sdk 3.6.3 → 3.6.4-beta3

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.
@@ -0,0 +1,90 @@
1
+ module.exports = function addAiTab(editorTabs, editorContent) {
2
+ let aiTab = {
3
+ id: 'editor-tab-ai',
4
+ label: 'AI',
5
+ name: 'AI',
6
+ content: $('<div>', {
7
+ class: 'editor-tray-content',
8
+ id: 'ai-tab',
9
+ css: { position: 'relative', height: '100%' }
10
+ })
11
+ .appendTo(editorContent)
12
+ .hide(),
13
+ iconClass: 'fa fa-magic',
14
+ };
15
+
16
+ const aiList = $('<div>', {
17
+ id: 'ai-list',
18
+ css: {
19
+ 'max-height': 'calc(100% - 120px)',
20
+ 'overflow-y': 'auto',
21
+ 'margin-bottom': '10px'
22
+ }
23
+ }).appendTo(aiTab.content);
24
+
25
+ const aiInputContainer = $('<div>', {
26
+ css: {
27
+ position: 'absolute',
28
+ left: 0,
29
+ right: 0,
30
+ bottom: 0,
31
+ padding: '10px',
32
+ 'background': '#f9f9f9',
33
+ 'box-shadow': '0 -1px 4px rgba(0,0,0,0.04)'
34
+ }
35
+ }).appendTo(aiTab.content);
36
+
37
+ const aiInput = $('<textarea>', {
38
+ id: 'ai-input',
39
+ rows: 3,
40
+ css: {
41
+ width: 'calc(100% - 110px)',
42
+ resize: 'none',
43
+ display: 'inline-block',
44
+ verticalAlign: 'bottom'
45
+ },
46
+ placeholder: 'Type your AI prompt...'
47
+ }).appendTo(aiInputContainer);
48
+
49
+ const aiSendBtn = $('<button>', {
50
+ text: 'Send',
51
+ class: 'editor-button primary',
52
+ css: {
53
+ float: 'right',
54
+ marginLeft: '10px',
55
+ width: '90px',
56
+ height: '48px',
57
+ position: 'relative',
58
+ bottom: '0'
59
+ }
60
+ }).appendTo(aiInputContainer);
61
+
62
+ aiSendBtn.on('click', function () {
63
+ const val = aiInput.val().trim();
64
+ if (val) {
65
+ const res = window.__kumologica.libs.chatAi({conversation: [], question: val});
66
+ console.log('AI Tab Sent:', val);
67
+ $('<div>', {
68
+ text: val,
69
+ css: {
70
+ padding: '6px 8px',
71
+ margin: '2px 0',
72
+ background: '#eaeaea',
73
+ borderRadius: '4px'
74
+ }
75
+ }).appendTo(aiList);
76
+ $('<div>', {
77
+ text: 'Response to your xtext: ' + res,
78
+ css: {
79
+ padding: '6px 8px',
80
+ margin: '2px 0',
81
+ background: '#d0f5d8',
82
+ borderRadius: '4px'
83
+ }
84
+ }).appendTo(aiList);
85
+ aiInput.val('');
86
+ }
87
+ });
88
+
89
+ editorTabs.addTab(aiTab);
90
+ };
@@ -1870,6 +1870,120 @@ RED.editor = (function () {
1870
1870
  nodeInfoEditor = buildDescriptionForm(descriptionTab.content, node);
1871
1871
  }
1872
1872
 
1873
+ // ...inside showEditDialog, after Help tab and before Notes tab...
1874
+
1875
+ // AI tab
1876
+ let aiTab = {
1877
+ id: 'editor-tab-ai',
1878
+ label: 'AI',
1879
+ name: 'AI',
1880
+ content: $('<div>', {
1881
+ class: 'editor-tray-content',
1882
+ id: 'ai-tab',
1883
+ css: { position: 'relative', height: '100%' }
1884
+ })
1885
+ .appendTo(editorContent)
1886
+ .hide(),
1887
+ iconClass: 'fa fa-magic',
1888
+ };
1889
+
1890
+ // List of text items (history/messages)
1891
+ const aiList = $('<div>', {
1892
+ id: 'ai-list',
1893
+ css: {
1894
+ 'max-height': 'calc(100% - 120px)',
1895
+ 'overflow-y': 'auto',
1896
+ 'margin-bottom': '10px'
1897
+ }
1898
+ }).appendTo(aiTab.content);
1899
+
1900
+ // Text editor area
1901
+ const aiInputContainer = $('<div>', {
1902
+ css: {
1903
+ position: 'absolute',
1904
+ left: 0,
1905
+ right: 0,
1906
+ bottom: 0,
1907
+ padding: '10px',
1908
+ 'background': '#f9f9f9',
1909
+ 'box-shadow': '0 -1px 4px rgba(0,0,0,0.04)'
1910
+ }
1911
+ }).appendTo(aiTab.content);
1912
+
1913
+ const aiInput = $('<textarea>', {
1914
+ id: 'ai-input',
1915
+ rows: 3,
1916
+ css: {
1917
+ width: 'calc(100% - 110px)',
1918
+ resize: 'none',
1919
+ display: 'inline-block',
1920
+ verticalAlign: 'bottom'
1921
+ },
1922
+ placeholder: 'Type your AI prompt...'
1923
+ }).appendTo(aiInputContainer);
1924
+
1925
+ // Send button
1926
+ const aiSendBtn = $('<button>', {
1927
+ text: 'Send',
1928
+ class: 'editor-button primary',
1929
+ css: {
1930
+ float: 'right',
1931
+ marginLeft: '10px',
1932
+ width: '90px',
1933
+ height: '48px',
1934
+ position: 'relative',
1935
+ bottom: '0'
1936
+ }
1937
+ }).appendTo(aiInputContainer);
1938
+
1939
+ aiSendBtn.on('click', async function () {
1940
+ const val = aiInput.val().trim();
1941
+ if (val) {
1942
+ // Log the sent text to the console
1943
+ console.log('AI Tab Sent:', val);
1944
+
1945
+
1946
+ let res;
1947
+
1948
+ try {
1949
+ res = await window.__kumologica.libs.chatAi({conversation: [], question: val});
1950
+ console.log('AI Tab Response:', res);
1951
+ } catch (error) {
1952
+ console.log('AI Tab err:', error);
1953
+ res = error;
1954
+ }
1955
+
1956
+ // Add the original text to the list, aligned right
1957
+ $('<div>', {
1958
+ text: val,
1959
+ css: {
1960
+ padding: '6px 8px',
1961
+ margin: '2px 0',
1962
+ background: '#eaeaea',
1963
+ borderRadius: '4px',
1964
+ textAlign: 'right',
1965
+ display: 'flex',
1966
+ justifyContent: 'flex-end'
1967
+ }
1968
+ }).appendTo(aiList);
1969
+
1970
+ // Add the response text to the list, aligned left
1971
+ $('<div>', {
1972
+ text: 'Response to your text: ' + res,
1973
+ css: {
1974
+ padding: '6px 8px',
1975
+ margin: '2px 0',
1976
+ background: '#d0f5d8',
1977
+ borderRadius: '4px',
1978
+ textAlign: 'left'
1979
+ }
1980
+ }).appendTo(aiList);
1981
+
1982
+ aiInput.val('');
1983
+ }
1984
+ });
1985
+ // editorTabs.addTab(aiTab);
1986
+
1873
1987
  var appearanceTab = {
1874
1988
  id: 'editor-tab-appearance',
1875
1989
  label: 'Appearance',
@@ -2120,7 +2234,7 @@ RED.editor = (function () {
2120
2234
  '<option value="' +
2121
2235
  ws.id +
2122
2236
  '"' +
2123
- (ws.id == editing_config_node.z ? ' selected' : '') +
2237
+ (ws.id == editing_config_node.z ? ' selected' : '') +
2124
2238
  '></option>'
2125
2239
  )
2126
2240
  .text(workspaceLabel)
@@ -8,10 +8,12 @@ RED.tray = (function () {
8
8
  $('#optionSettings').removeClass('node-property-selected');
9
9
  $('#optionHelp').removeClass('node-property-selected');
10
10
  $('#optionDocumentation').removeClass('node-property-selected');
11
+ $('#optionAi').removeClass('node-property-selected');
11
12
 
12
13
  $('#properties-tab').hide();
13
14
  $('#help-tab').hide();
14
15
  $('#documentation-tab').hide();
16
+ $('#ai-tab').hide();
15
17
 
16
18
  domEl.addClass('node-property-selected');
17
19
 
@@ -25,6 +27,9 @@ RED.tray = (function () {
25
27
  case 'notes':
26
28
  $('#documentation-tab').show();
27
29
  break;
30
+ case 'ai':
31
+ $('#ai-tab').show();
32
+ break;
28
33
  }
29
34
  }
30
35
 
@@ -47,6 +52,7 @@ RED.tray = (function () {
47
52
  <div id="optionSettings" class="node-property-option node-property-selected">Settings</div>
48
53
  <div id="optionHelp" class="node-property-option">Help</div>
49
54
  <div id="optionDocumentation" class="node-property-option">Notes</div>
55
+ <!--<div id="optionAi" class="node-property-option">AI</div>-->
50
56
  </div>
51
57
  `).appendTo(el);
52
58
  }
@@ -263,6 +269,10 @@ RED.tray = (function () {
263
269
  let $this = $(e.currentTarget);
264
270
  selectOption($this, 'help');
265
271
  });
272
+ $('#optionAi').click((e) => {
273
+ let $this = $(e.currentTarget);
274
+ selectOption($this, 'ai');
275
+ });
266
276
  $('#optionDocumentation').click((e) => {
267
277
  let $this = $(e.currentTarget);
268
278
  selectOption($this, 'notes');
@@ -1,39 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const archiver = require('archiver');
6
- const BbPromise = require('bluebird');
7
- const walkDirSync = require('./walk-dir-sync');
8
-
9
- async function createZipFile(srcDirPath, outputFilePath) {
10
- const files = walkDirSync(srcDirPath).map((file) => ({
11
- input: file,
12
- output: file.replace(path.join(srcDirPath, path.sep), ''),
13
- }));
14
-
15
- return new BbPromise((resolve, reject) => {
16
- const output = fs.createWriteStream(outputFilePath);
17
- const archive = archiver('zip', {
18
- zlib: { level: 9 },
19
- });
20
-
21
- output.on('open', () => {
22
- archive.pipe(output);
23
-
24
- files.forEach((file) => {
25
- // TODO: update since this is REALLY slow
26
- if (fs.lstatSync(file.input).isFile()) {
27
- archive.append(fs.createReadStream(file.input), { name: file.output });
28
- }
29
- });
30
-
31
- archive.finalize();
32
- });
33
-
34
- archive.on('error', (err) => reject(err));
35
- output.on('close', () => resolve(outputFilePath));
36
- });
37
- }
38
-
39
- module.exports = createZipFile;