@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.
- package/cli/commands/run.js +4 -3
- package/package.json +5 -6
- package/src/app/lib/ai/chatai.js +206 -0
- package/src/app/preload.js +6 -0
- package/src/app/ui/editor-client/public/red/red.js +125 -1
- package/src/app/ui/editor-client/public/red/red.min.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/aitab.js +90 -0
- package/src/app/ui/editor-client/src/js/ui/editor.js +115 -1
- package/src/app/ui/editor-client/src/js/ui/tray.js +10 -0
- package/cli/utils/fs/create-zip-file.js +0 -39
|
@@ -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
|
-
|
|
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;
|