@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.
- package/cli/commands/create-commands/openapi.js +42 -0
- package/cli/commands/create.js +17 -8
- package/cli/commands/login.js +87 -0
- package/package.json +18 -7
- package/src/app/lib/ai/layout.js +75 -0
- package/src/app/lib/ai/openai.js +108 -0
- package/src/app/lib/ai/prompt.txt +583 -0
- package/src/app/lib/aws/ca-cloudwatch-api.js +2 -10
- package/src/app/lib/aws/ca-dynamodb-api.js +6 -10
- package/src/app/lib/aws/ca-elb-api.js +4 -24
- package/src/app/lib/aws/ca-events-api.js +5 -12
- package/src/app/lib/aws/ca-iot-api.js +3 -87
- package/src/app/lib/aws/ca-s3-api.js +17 -62
- package/src/app/lib/aws/ca-sns-api.js +6 -15
- package/src/app/lib/aws/ca-sqs-api.js +9 -6
- package/src/app/lib/aws/index.js +70 -86
- package/src/app/lib/aws/kl-apigw-api.js +40 -0
- package/src/app/lib/aws/kl-iam-api.js +5 -5
- package/src/app/lib/github/index.js +0 -17
- package/src/app/lib/serverless/index.js +1 -1
- package/src/app/lib/stores/settings-cloud-store.js +35 -2
- package/src/app/main.js +34 -32
- package/src/app/preload.js +36 -28
- package/src/app/ui/editor-client/public/red/red.js +924 -458
- package/src/app/ui/editor-client/public/red/red.min.js +2 -2
- package/src/app/ui/editor-client/public/red/style.min.css +1 -1
- package/src/app/ui/editor-client/src/js/nodes.js +19 -18
- package/src/app/ui/editor-client/src/js/red.js +6 -3
- package/src/app/ui/editor-client/src/js/ui/editor.js +70 -70
- package/src/app/ui/editor-client/src/js/ui/footer.js +143 -0
- package/src/app/ui/editor-client/src/js/ui/search.js +43 -34
- package/src/app/ui/editor-client/src/js/ui/sidebar.js +26 -24
- package/src/app/ui/editor-client/src/js/ui/signup.js +56 -0
- package/src/app/ui/editor-client/src/js/ui/tab-ai.js +210 -0
- package/src/app/ui/editor-client/src/js/ui/tab-awsDeploy.js +30 -5
- package/src/app/ui/editor-client/src/js/ui/tab-test.js +120 -99
- package/src/app/ui/editor-client/src/js/ui/update-panel.js +0 -1
- package/src/app/ui/editor-client/src/js/ui/view.js +201 -202
- package/src/app/ui/editor-client/src/sass/editor.scss +715 -645
- package/src/app/ui/editor-client/src/sass/sidebar.scss +21 -12
- package/src/app/ui/editor-client/src/sass/style.scss +101 -0
- package/src/app/ui/editor-client/src/sass/tab-ai.scss +68 -0
- package/src/app/ui/editor-client/src/sass/workspace.scss +12 -2
- package/src/app/ui/editor-client/templates/index.mst +41 -7
- package/src/server/DesignerServer.js +2 -1
- package/cli/.DS_Store +0 -0
- package/fixtures/.DS_Store +0 -0
- package/src/app/lib/aws/ca-apigw-api.js +0 -216
- package/src/app/lib/aws/ca-codecommit-api.js +0 -63
- package/src/app/lib/aws/kl-rekognition-api.js +0 -66
- package/src/app/lib/aws/kl-ssm-api.js +0 -24
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const pathlib = require('path');
|
|
2
|
+
const { prompt, Select } = require('enquirer');
|
|
3
|
+
const { logNotice, logError } = require('../../utils/logger');
|
|
4
|
+
const { downloadTemplateFromRepo, listAvailableTemplates } = require('../../utils/download-template-from-repo');
|
|
5
|
+
|
|
6
|
+
async function createProjectIteratively(){
|
|
7
|
+
const availableTemplates = await listAvailableTemplates();
|
|
8
|
+
// Project name
|
|
9
|
+
const projectNameResponse = await prompt({
|
|
10
|
+
type: 'input',
|
|
11
|
+
name: 'projectName',
|
|
12
|
+
message: 'Enter the name for the project'
|
|
13
|
+
});
|
|
14
|
+
let aProjectName = projectNameResponse.projectName;
|
|
15
|
+
|
|
16
|
+
// Target Path
|
|
17
|
+
const directoryResponse = await prompt({
|
|
18
|
+
type: 'input',
|
|
19
|
+
name: 'directory',
|
|
20
|
+
message: 'Enter the path where the project will be created '
|
|
21
|
+
});
|
|
22
|
+
let aProjectPath = directoryResponse.directory;
|
|
23
|
+
|
|
24
|
+
// Template name
|
|
25
|
+
const promptTemplate = new Select({
|
|
26
|
+
name: 'template',
|
|
27
|
+
message: 'Pick one of the available templates',
|
|
28
|
+
choices: availableTemplates
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
let aTemplateName = await promptTemplate.run();
|
|
32
|
+
|
|
33
|
+
try{
|
|
34
|
+
await downloadTemplateFromRepo(undefined, aTemplateName, aProjectPath, aProjectName);
|
|
35
|
+
logNotice(`Successfully created project: ${pathlib.join(aProjectPath, aProjectName)}`)
|
|
36
|
+
} catch (err){
|
|
37
|
+
logError(`Error found while creating project due to: ${err.message}`)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
module.exports = createProjectIteratively;
|
package/cli/commands/create.js
CHANGED
|
@@ -20,32 +20,41 @@ exports.builder = (yargs) => {
|
|
|
20
20
|
alias: 't',
|
|
21
21
|
nargs: 1
|
|
22
22
|
})
|
|
23
|
+
yargs.option(`api`, {
|
|
24
|
+
describe: `OpenApi/Swagger definition of the api`,
|
|
25
|
+
type: 'string',
|
|
26
|
+
alias: 'a',
|
|
27
|
+
nargs: 1
|
|
28
|
+
})
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
exports.desc = 'Create a kumologica project. Do not pass any options to create iteratively.'
|
|
27
|
-
exports.handler = async ({ path, template }) => {
|
|
33
|
+
exports.handler = async ({ path, template, api }) => {
|
|
28
34
|
const { version } = require('../../package.json');
|
|
29
35
|
|
|
30
|
-
if (!path && !template) {
|
|
36
|
+
if (!path && !template && !api) {
|
|
31
37
|
await createProjectIteratively();
|
|
38
|
+
|
|
32
39
|
} else if (!path && template) {
|
|
33
|
-
try{
|
|
40
|
+
try {
|
|
34
41
|
await downloadTemplateFromRepo(undefined, template, process.cwd(), template);
|
|
35
|
-
logNotice(`Successfully created project: ${ pathlib.join(process.cwd(), template)}`);
|
|
36
|
-
}catch(e){
|
|
42
|
+
logNotice(`Successfully created project: ${ pathlib.join(process.cwd(), template)}`);
|
|
43
|
+
} catch(e) {
|
|
37
44
|
logError(e.message);
|
|
38
45
|
}
|
|
46
|
+
|
|
39
47
|
} else if (path && !template){
|
|
40
|
-
try{
|
|
48
|
+
try {
|
|
41
49
|
codegen.generateBoilerplateProject({
|
|
42
50
|
basePath :process.cwd(),
|
|
43
51
|
projectName: path,
|
|
44
52
|
runtimeVersion: version });
|
|
45
53
|
logNotice(`Successfully created project: ${ pathlib.join(process.cwd(), path)}`);
|
|
46
|
-
}catch(e){
|
|
54
|
+
} catch(e) {
|
|
47
55
|
logError(e.message);
|
|
48
56
|
}
|
|
57
|
+
|
|
49
58
|
} else if (path && template) {
|
|
50
59
|
path = pathlib.resolve(path);
|
|
51
60
|
let projectPath = pathlib.dirname(path);
|
|
@@ -57,7 +66,7 @@ exports.handler = async ({ path, template }) => {
|
|
|
57
66
|
await downloadTemplateFromRepo(undefined, template, projectPath, projectName);
|
|
58
67
|
}
|
|
59
68
|
logNotice(`Successfully created project: ${path}`);
|
|
60
|
-
}catch(e){
|
|
69
|
+
} catch(e) {
|
|
61
70
|
logError(e.message);
|
|
62
71
|
}
|
|
63
72
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
|
|
2
|
+
const { prompt, Select } = require('enquirer');
|
|
3
|
+
|
|
4
|
+
exports.command = 'login';
|
|
5
|
+
exports.desc = `Login to kumologica.dev`;
|
|
6
|
+
|
|
7
|
+
exports.builder = {
|
|
8
|
+
|
|
9
|
+
"email": {
|
|
10
|
+
describe: "Valid email address for login",
|
|
11
|
+
type: 'string',
|
|
12
|
+
alias: 'e',
|
|
13
|
+
nargs: 1
|
|
14
|
+
},
|
|
15
|
+
"password": {
|
|
16
|
+
describe: "Password for login.",
|
|
17
|
+
type: 'string',
|
|
18
|
+
alias: 'p',
|
|
19
|
+
nargs: 1
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function login(email, password) {
|
|
24
|
+
const { CognitoIdentityProviderClient, InitiateAuthCommand } = require("@aws-sdk/client-cognito-identity-provider");
|
|
25
|
+
const client = new CognitoIdentityProviderClient();
|
|
26
|
+
|
|
27
|
+
const input = {
|
|
28
|
+
AuthFlow: "USER_PASSWORD_AUTH",
|
|
29
|
+
AuthParameters: {
|
|
30
|
+
PASSWORD: password,
|
|
31
|
+
USERNAME: email
|
|
32
|
+
},
|
|
33
|
+
ClientId: "5qm756mn3otap8o8f2vf6vqj96"
|
|
34
|
+
};
|
|
35
|
+
const command = new InitiateAuthCommand(input);
|
|
36
|
+
const response = await client.send(command);
|
|
37
|
+
console.log(JSON.stringify(response, null, 2));
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
exports.handler = async function (argv) {
|
|
44
|
+
|
|
45
|
+
const chalk = require('chalk');
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
let email;
|
|
49
|
+
|
|
50
|
+
if (argv.email) {
|
|
51
|
+
email = argv.email;
|
|
52
|
+
} else {
|
|
53
|
+
const emailPrompt = await prompt({
|
|
54
|
+
type: 'input',
|
|
55
|
+
name: 'email',
|
|
56
|
+
message: 'Enter valid email address to be used for login'
|
|
57
|
+
});
|
|
58
|
+
email = emailPrompt.email;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`\Logging in to komologica.dev using email: ${email}\n`);
|
|
62
|
+
|
|
63
|
+
let pwd;
|
|
64
|
+
|
|
65
|
+
if (argv.password) {
|
|
66
|
+
pwd = argv.password;
|
|
67
|
+
} else {
|
|
68
|
+
const pwdPrompt = await prompt({
|
|
69
|
+
type: 'input',
|
|
70
|
+
name: 'password',
|
|
71
|
+
message: 'Enter password.'
|
|
72
|
+
});
|
|
73
|
+
pwd = pwdPrompt.password;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await login(email, pwd);
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
console.log(chalk.greenBright('Login successful.'));
|
|
80
|
+
|
|
81
|
+
process.exit(0);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
|
|
84
|
+
console.log(`${chalk.redBright(e.message)}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kumologica/sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0-beta2",
|
|
4
4
|
"productName": "Kumologica Designer",
|
|
5
5
|
"copyright": "Copyright 2020 Kumologica Pty Ltd, All Rights Reserved.",
|
|
6
6
|
"author": "Kumologica Pty Ltd <contact@kumologica.com>",
|
|
@@ -63,14 +63,24 @@
|
|
|
63
63
|
},
|
|
64
64
|
"license": "Proprietary",
|
|
65
65
|
"dependencies": {
|
|
66
|
+
"@aws-sdk/client-api-gateway": "^3.556.0",
|
|
67
|
+
"@aws-sdk/client-cloudformation": "^3.556.0",
|
|
68
|
+
"@aws-sdk/client-cloudwatch-events": "^3.556.0",
|
|
69
|
+
"@aws-sdk/client-dynamodb-streams": "^3.556.0",
|
|
70
|
+
"@aws-sdk/client-elastic-load-balancing-v2": "^3.556.0",
|
|
71
|
+
"@aws-sdk/client-iam": "^3.556.0",
|
|
72
|
+
"@aws-sdk/client-iot": "^3.556.0",
|
|
73
|
+
"@aws-sdk/client-s3": "^3.556.0",
|
|
74
|
+
"@aws-sdk/client-sns": "^3.556.0",
|
|
75
|
+
"@aws-sdk/client-sqs": "^3.556.0",
|
|
76
|
+
"@aws-sdk/credential-providers": "^3.556.0",
|
|
66
77
|
"@electron/remote": "^2.0.8",
|
|
67
|
-
"@kumologica/builder": "3.
|
|
68
|
-
"@kumologica/devkit": "3.
|
|
69
|
-
"@kumologica/runtime": "3.
|
|
78
|
+
"@kumologica/builder": "3.5.0-beta2",
|
|
79
|
+
"@kumologica/devkit": "3.5.0-beta2",
|
|
80
|
+
"@kumologica/runtime": "3.5.0-beta2",
|
|
70
81
|
"adm-zip": "0.4.13",
|
|
71
82
|
"ajv": "8.10.0",
|
|
72
83
|
"archive-type": "^4.0.0",
|
|
73
|
-
"aws-sdk": "2.513.0",
|
|
74
84
|
"basic-auth": "2.0.1",
|
|
75
85
|
"bcryptjs": "2.4.3",
|
|
76
86
|
"bluebird": "^3.7.2",
|
|
@@ -111,6 +121,7 @@
|
|
|
111
121
|
"mime": "2.4.4",
|
|
112
122
|
"mustache": "3.0.1",
|
|
113
123
|
"oauth2orize": "1.11.0",
|
|
124
|
+
"openai": "^4.28.4",
|
|
114
125
|
"os": "0.1.1",
|
|
115
126
|
"p-event": "^5.0.1",
|
|
116
127
|
"passport": "0.4.0",
|
|
@@ -164,9 +175,9 @@
|
|
|
164
175
|
"typescript": "^3.5.3"
|
|
165
176
|
},
|
|
166
177
|
"engines": {
|
|
167
|
-
"node": ">=
|
|
178
|
+
"node": ">=18"
|
|
168
179
|
},
|
|
169
180
|
"kumologica": {
|
|
170
|
-
"dev":
|
|
181
|
+
"dev": true
|
|
171
182
|
}
|
|
172
183
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const dagre = require('dagre');
|
|
2
|
+
|
|
3
|
+
const NODE_SIZE = 45;
|
|
4
|
+
const NODE_SEP = 50;
|
|
5
|
+
const MARGIN_X = 50;
|
|
6
|
+
const MARGIN_Y = 50;
|
|
7
|
+
|
|
8
|
+
function applyLayout(nodes) {
|
|
9
|
+
let layarizedFlow = [];
|
|
10
|
+
|
|
11
|
+
let tabs = nodes.filter(n => n.type === 'tab');
|
|
12
|
+
// No tab, most likely a single nod
|
|
13
|
+
if (tabs.length === 0) {
|
|
14
|
+
let tabIds = [...new Set(nodes.map(item => item.z))];
|
|
15
|
+
tabIds.map(tabId => {
|
|
16
|
+
layarizedFlow.push(...applyTabLayout(nodes, tabId));
|
|
17
|
+
})
|
|
18
|
+
} else {
|
|
19
|
+
tabs.map(tab => {
|
|
20
|
+
layarizedFlow.push(tab);
|
|
21
|
+
layarizedFlow.push(...applyTabLayout(nodes, tab.id));
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return layarizedFlow;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function applyTabLayout(nodes, tabId) {
|
|
29
|
+
let nodesOnTab = nodes.filter(n => n.z === tabId) || [];
|
|
30
|
+
|
|
31
|
+
// Prepare the graph
|
|
32
|
+
let g = new dagre.graphlib.Graph();
|
|
33
|
+
|
|
34
|
+
// Set an object for the graph label
|
|
35
|
+
g.setGraph({
|
|
36
|
+
rankdir: "LR",
|
|
37
|
+
nodesep: NODE_SEP,
|
|
38
|
+
marginx: MARGIN_X,
|
|
39
|
+
marginy: MARGIN_Y
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Default to assigning a new object as a label for each new edge.
|
|
43
|
+
g.setDefaultEdgeLabel(function () { return {}; });
|
|
44
|
+
|
|
45
|
+
// Create nodes for the graph
|
|
46
|
+
nodesOnTab.forEach(n => {
|
|
47
|
+
g.setNode(n.id, { label: n.name, width: NODE_SIZE, height: NODE_SIZE })
|
|
48
|
+
|
|
49
|
+
// TODO - Check the wires here and create the edge
|
|
50
|
+
if (n.wires && Array.isArray(n.wires) && n.wires.length > 0) {
|
|
51
|
+
n.wires.forEach(wire => {
|
|
52
|
+
g.setEdge(n.id, wire)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
dagre.layout(g);
|
|
58
|
+
|
|
59
|
+
// Apply the coordinates
|
|
60
|
+
g.nodes().forEach(nid => {
|
|
61
|
+
if (nid) {
|
|
62
|
+
let node = nodesOnTab.find(n => n.id === nid);
|
|
63
|
+
if (node) {
|
|
64
|
+
node.x = g.node(nid).x;
|
|
65
|
+
node.y = Number.isNaN(g.node(nid).y) ? 0 : g.node(nid).y;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return nodesOnTab;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
applyLayout
|
|
75
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const OpenAI = require('openai');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { applyLayout } = require('./layout');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
require('dotenv').config()
|
|
8
|
+
|
|
9
|
+
// utils
|
|
10
|
+
function unescapeObject(obj) {
|
|
11
|
+
// Check if the input is an object
|
|
12
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
13
|
+
return obj; // Return as is if not an object
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Iterate over each property of the object
|
|
17
|
+
for (let key in obj) {
|
|
18
|
+
if (obj.hasOwnProperty(key)) {
|
|
19
|
+
// If the property is a string, unescape it
|
|
20
|
+
if (typeof obj[key] === 'string') {
|
|
21
|
+
obj[key] = unescapeString(obj[key]);
|
|
22
|
+
}
|
|
23
|
+
// If the property is an object, recursively unescape its properties
|
|
24
|
+
else if (typeof obj[key] === 'object') {
|
|
25
|
+
obj[key] = unescapeObject(obj[key]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return obj;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Function to unescape a string
|
|
34
|
+
function unescapeString(str) {
|
|
35
|
+
// Remove all occurrences of "\n
|
|
36
|
+
str = str.replace(/\\n\s*|\\n/g, '');
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
return str.replace(/\\(.)/g, function (_, char) {
|
|
40
|
+
switch (char) {
|
|
41
|
+
case 'n': return '\n'; // Replace '\n' with newline character
|
|
42
|
+
case 't': return '\t'; // Replace '\t' with tab character
|
|
43
|
+
case 'r': return '\r'; // Replace '\r' with carriage return character
|
|
44
|
+
case 'b': return '\b'; // Replace '\b' with backspace character
|
|
45
|
+
case 'f': return '\f'; // Replace '\f' with form feed character
|
|
46
|
+
case '\\': return '\\'; // Replace '\\' with backslash character
|
|
47
|
+
case '"': return '"'; // Replace '\"' with double quote character
|
|
48
|
+
case "'": return "'"; // Replace "\'" with single quote character
|
|
49
|
+
default: return char; // Return the character as is if not an escape sequence
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class OpenAIClient {
|
|
56
|
+
// attributes
|
|
57
|
+
openai = null;
|
|
58
|
+
version = null;
|
|
59
|
+
|
|
60
|
+
constructor(props) {
|
|
61
|
+
this.openai = new OpenAI({
|
|
62
|
+
apiKey: props.key || process.env.OPENAI_API_KEY || '***',
|
|
63
|
+
dangerouslyAllowBrowser: true
|
|
64
|
+
});
|
|
65
|
+
this.version = props.version || 'gpt-3.5-turbo';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getSystemPrompt() {
|
|
69
|
+
if (!this.systemPrompt) {
|
|
70
|
+
try {
|
|
71
|
+
this.systemPrompt = fs.readFileSync(path.join(__dirname, 'prompt.txt'), 'utf-8');
|
|
72
|
+
} catch (err) {
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return this.systemPrompt;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async t2c(userTask) {
|
|
80
|
+
let userMessage = `
|
|
81
|
+
Generate kumologica flow. Do not include any extra explanation, just the json document. For the following user description:
|
|
82
|
+
${userTask}`;
|
|
83
|
+
try {
|
|
84
|
+
let spec = this.getSystemPrompt();
|
|
85
|
+
const chatCompletion = await this.openai.chat.completions.create({
|
|
86
|
+
model: this.version,
|
|
87
|
+
messages: [
|
|
88
|
+
{ role: 'system', content: spec },
|
|
89
|
+
{ role: 'user', content: userMessage }
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const resp = chatCompletion.choices[0].message.content;
|
|
94
|
+
console.log('[openai] Resp=', resp);
|
|
95
|
+
const respo = JSON.parse(resp);
|
|
96
|
+
console.log('[openai] Resp.flow=', JSON.parse(respo.flow));
|
|
97
|
+
console.log('[openai] Unscaped - Resp.flow', unescapeObject(JSON.parse(respo.flow)));
|
|
98
|
+
return applyLayout(unescapeObject(JSON.parse(respo.flow)));
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.log(err);
|
|
101
|
+
throw new Error(err.toString());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
OpenAIClient
|
|
108
|
+
}
|