@kumologica/sdk 4.0.0-beta9 → 4.0.1

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.
@@ -1,6 +1,7 @@
1
1
  const path = require("path");
2
2
  const { spawn } = require("child_process");
3
- const { Updater } = require("@kumologica/builder");
3
+ const { Updater, checkSDK } = require("@kumologica/builder");
4
+
4
5
  const { confirm } = require("enquirer");
5
6
 
6
7
  const { logError } = require("../utils/logger");
@@ -138,6 +139,26 @@ async function promptUpdates(updates) {
138
139
  return false;
139
140
  }
140
141
 
142
+ async function checkSDKVersion() {
143
+
144
+ try {
145
+ const sdkVersion = await checkSDK.checkSDK();
146
+
147
+ if (!sdkVersion || sdkVersion === "") {
148
+ return;
149
+ }
150
+
151
+ console.log("");
152
+ console.log(`-----------------------------------------------------`);
153
+ console.log(`New version of Kumologica SDK is now available: ${sdkVersion}`);
154
+ console.log("To update, run: npm install -g @kumologica/sdk");
155
+ console.log(`-----------------------------------------------------`);
156
+ console.log("");
157
+ }catch (e) {
158
+ return;
159
+ }
160
+ }
161
+
141
162
  /*
142
163
  check if upgrade in npmjs to the existing ones in package.json
143
164
  check if upgrade or missing node_modules vs package.json
@@ -148,6 +169,7 @@ async function runUpdater(projectDir) {
148
169
  console.debug("Project directory not provided, skipping upgrade check");
149
170
  return;
150
171
  }
172
+
151
173
  const updater = new Updater(projectDir);
152
174
  const updates = await updater.checkForUpdates();
153
175
 
@@ -166,9 +188,9 @@ async function runUpdater(projectDir) {
166
188
  }
167
189
 
168
190
  async function licenseCheck() {
169
-
170
191
  const license = require("../utils/license.js");
171
- return await license.licenseCheck();
192
+ const res = await license.licenseCheck();
193
+ return res;
172
194
  }
173
195
 
174
196
  exports.command = "open [project_directory]";
@@ -183,15 +205,18 @@ exports.desc = "Open Kumologica Designer";
183
205
 
184
206
  exports.handler = async ({ project_directory }) => {
185
207
 
208
+ await checkSDKVersion();
209
+
186
210
  const projectDir = project_directory
187
211
  ? path.resolve(project_directory)
188
212
  : undefined;
189
213
 
190
- if (!await licenseCheck(project_directory)) {
214
+ if (!await licenseCheck()) {
191
215
  process.exit(1);
192
216
  }
193
217
 
194
218
  await runUpdater(projectDir);
195
219
 
220
+
196
221
  startElectron(projectDir);
197
222
  };
@@ -70,8 +70,10 @@ async function promptForLicenseKey() {
70
70
 
71
71
  console.log(`📧 Developer license will be requested for: ${email}`);
72
72
 
73
- await tools.license.subscribe(email);
74
- console.log(`Follow the instructions in your email to complete the process.`);
73
+ const res = await tools.license.subscribe(email);
74
+ if (res) {
75
+ console.log(`Follow the instructions in your email to complete the process.`);
76
+ }
75
77
 
76
78
  return false;
77
79
  } else {
@@ -92,15 +94,16 @@ async function licenseCheck() {
92
94
  console.log("Reading license data...");
93
95
  try {
94
96
  const licenseData = tools.license.read(getHomeDir());
95
- return true;
97
+ if (licenseData != null) {
98
+ return true;
99
+ }
100
+
96
101
  } catch (e) {
97
102
  console.error("Error reading license data:", e.message);
98
103
  }
99
104
 
100
105
  console.log("No license data...");
101
- await promptForLicenseKey();
102
-
103
- return false;
106
+ return await promptForLicenseKey();
104
107
  }
105
108
 
106
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumologica/sdk",
3
- "version": "4.0.0-beta9",
3
+ "version": "4.0.1",
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>",
@@ -88,9 +88,9 @@
88
88
  "@aws-sdk/signature-v4": "^3.370.0",
89
89
  "@aws-sdk/types": "^3.936.0",
90
90
  "@electron/remote": "^2.0.8",
91
- "@kumologica/builder": "4.0.0-beta9",
92
- "@kumologica/devkit": "4.0.0-beta9",
93
- "@kumologica/runtime": "4.0.0-beta9",
91
+ "@kumologica/builder": "4.0.1",
92
+ "@kumologica/devkit": "4.0.1",
93
+ "@kumologica/runtime": "4.0.1",
94
94
  "ajv": "8.10.0",
95
95
  "archive-type": "^4.0.0",
96
96
  "basic-auth": "2.0.1",
@@ -127,7 +127,7 @@
127
127
  "js-yaml": "3.13.1",
128
128
  "json-cycle": "^1.3.0",
129
129
  "jsonata": "1.7.0",
130
- "jsonpath": "1.0.2",
130
+ "jsonpath": "1.3.0",
131
131
  "make-dir": "^3.1.0",
132
132
  "memorystore": "1.6.1",
133
133
  "mime": "2.4.4",
@@ -179,8 +179,8 @@
179
179
  "grunt-terser": "2.0.0",
180
180
  "istanbul": "^0.4.5",
181
181
  "license-checker": "^25.0.1",
182
- "license-compatibility-checker": "^0.3.4",
183
- "license-report": "^3.0.0",
182
+ "license-compatibility-checker": "^0.3.5",
183
+ "license-report": "^6.8.2",
184
184
  "mocha": "10.2.0",
185
185
  "node-sass": "9.0.0",
186
186
  "tslint": "^5.18.0",
@@ -44,9 +44,19 @@ const got = require('got');
44
44
 
45
45
  const PROMPT_URL = 'https://kumologica.com/ai/kumologica-prompt.md';
46
46
  const FILENAME_PREFIX = 'kumologica-prompt';
47
+ const CHAT_HISTORY_FILENAME = 'kumologica-chat-history.json';
47
48
  const FILE_EXTENSION = '.md';
48
49
  const MAX_AGE_DAYS = 7;
49
50
 
51
+ const emptyHistory =
52
+ [
53
+ {
54
+ timestamp: 'latest',
55
+ title: 'Latest Chat',
56
+ messages: []
57
+ }
58
+ ];
59
+
50
60
  class AiConfigStore {
51
61
  // aiConfigFileFullPath: a string representing the full path of the ai config file
52
62
 
@@ -56,6 +66,8 @@ class AiConfigStore {
56
66
  const credsFile = `ai`;
57
67
 
58
68
  this.aiConfigFileFullPath = path.join(homedir, credsDir, credsFile);
69
+ this.chatHistoryFileFullPath = path.join(homedir, credsDir, CHAT_HISTORY_FILENAME);
70
+
59
71
  this.promptDirectory = path.join(homedir, credsDir);
60
72
 
61
73
  // check whether the config file exist or not: ~/.kumologica/ai
@@ -66,6 +78,14 @@ class AiConfigStore {
66
78
  fs.writeFileSync(this.aiConfigFileFullPath, defaultContent);
67
79
  }
68
80
 
81
+ // check whether the chat history file exist or not: ~/.kumologica/ai
82
+ if (!fs.existsSync(this.chatHistoryFileFullPath)){
83
+ // create file and write default content on it
84
+ console.log(`Creating AI chat history file on: ${this.chatHistoryFileFullPath}...`)
85
+ fsx.ensureDirSync(path.join(homedir, credsDir));
86
+ fs.writeFileSync(this.chatHistoryFileFullPath, JSON.stringify(emptyHistory));
87
+ }
88
+
69
89
  this.initFile = this.parseAiConfigFile();
70
90
  this.syncPrompt();
71
91
  }
@@ -116,7 +136,6 @@ class AiConfigStore {
116
136
  }
117
137
  }
118
138
 
119
-
120
139
  async syncPrompt() {
121
140
  const files = this.getPromptFiles();
122
141
  const newest = files[0] || null;
@@ -152,7 +171,7 @@ class AiConfigStore {
152
171
  }
153
172
 
154
173
  parseAiConfigFile() {
155
- this.initFile = ini.parse(this.readAiConfigFile());
174
+ this.initFile = this.unnestIni(ini.parse(this.readAiConfigFile()));
156
175
  return this.initFile;
157
176
  }
158
177
 
@@ -187,6 +206,92 @@ class AiConfigStore {
187
206
 
188
207
  return lines.map(l => l.trim()).join('\n');
189
208
  }
209
+
210
+ // history management methods
211
+ //
212
+ // the structure of chatHistory is an array of histories
213
+ // each history is an object of timestamp, title and array of messages
214
+ // the latest chat history is not timestamped but has a value of latest
215
+ //
216
+ readChatHistory() {
217
+ try {
218
+ const data = fs.readFileSync(this.chatHistoryFileFullPath, "utf-8");
219
+ const chatHistory = JSON.parse(data);
220
+ return chatHistory;
221
+ } catch (err) {
222
+ console.error('Failed to read chat history file:', err.message);
223
+ return emptyHistory;
224
+ }
225
+ }
226
+
227
+ getChat(timestamp) {
228
+ const chatHistory = this.readChatHistory();
229
+ return chatHistory.find(h => h.timestamp === timestamp);
230
+ }
231
+
232
+ writeChatHistoryFile(content) {
233
+ fs.writeFileSync(this.chatHistoryFileFullPath, content);
234
+ }
235
+
236
+ updateChatHistory(timestamp, messages) {
237
+ let chatHistory = this.readChatHistory();
238
+
239
+ let chat = chatHistory.find(h => h.timestamp === timestamp);
240
+ if (chat) {
241
+ chat.messages = messages;
242
+ this.writeChatHistoryFile(JSON.stringify(chatHistory));
243
+ } else {
244
+ console.error(`Chat history with timestamp ${timestamp} not found.`);
245
+ }
246
+ }
247
+
248
+ newLatestChat() {
249
+ let chatHistory = this.readChatHistory() || [];
250
+
251
+ let chat = chatHistory.find(h => h.timestamp === "latest");
252
+ if (chat) {
253
+ chat.timestamp = new Date().toISOString();
254
+ }
255
+ chatHistory.push({
256
+ timestamp: 'latest',
257
+ title: 'Latest Chat',
258
+ messages: []
259
+ });
260
+ this.writeChatHistoryFile(JSON.stringify(chatHistory));
261
+ }
262
+
263
+ unnestIni(parsed) {
264
+ const result = {};
265
+
266
+ function recurse(obj, path = '') {
267
+ for (const key in obj) {
268
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
269
+
270
+ const val = obj[key];
271
+ const fullPath = path ? `${path}.${key}` : key;
272
+
273
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
274
+ // Check if this object contains only primitive values (i.e. it's a real section)
275
+ const isSectionContent = Object.values(val).every(
276
+ v => typeof v !== 'object' || v === null
277
+ );
278
+
279
+ if (isSectionContent) {
280
+ result[fullPath] = val; // ← this is what you want
281
+ } else {
282
+ recurse(val, fullPath); // deeper nesting in section name
283
+ }
284
+ } else {
285
+ // rare top-level key=value outside any section
286
+ result[fullPath] = val;
287
+ }
288
+ }
289
+ }
290
+
291
+ recurse(parsed);
292
+ return result;
293
+ }
294
+
190
295
  }
191
296
 
192
297
  module.exports = {
@@ -146,7 +146,8 @@ class CloudConfigStore {
146
146
 
147
147
  return lines.map(l => l.trim()).join('\n');
148
148
  }
149
- }
149
+
150
+ }
150
151
 
151
152
  module.exports = {
152
153
  CloudConfigStore
@@ -1 +1 @@
1
- var e,o,n,t,r=require("crypto"),s=require("fs"),i=require("path");function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function c(){if(!o){o=1;let l="base64";e={subscribe:async function(e){console.log("Requesting license for email: "+e);var r=await fetch("https://api.infra.kumologica.com/p/signup?x-api-key=RjibYF3qZb2AzmTrPOnV35LfRV798e3Z87vp4izo",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e})});if(r.ok)return!0;{let e=await r.text();return console.error(`License request failed: ${r.status} `+e),!1}},display:function(e){e?(console.log("-------- License Details ----------"),console.log("Subscriber: "+e.sub),console.log("Email: "+e.email),console.log("License Type: "+e.licenseType),console.log("Issued For: "+(e.name||e.email)),console.log("Issued By: "+e.iss),console.log("Issued At: "+new Date(e.iat).toLocaleString()),console.log("Expiry: "+("perpetual"===e.exp?"Perpetual":new Date(e.exp).toLocaleString())),console.log("-----------------------------------")):console.error("Invalid license data.")},verify:function(e){publicKeyPem=(()=>{var o=Buffer.from("XkI1bxBWOXhHBztkdXIuEXlKLBcSIWstZlEzOEADPyFCCVkUeQNIIxwWDU4QEiEyLHpfOjwHCVNlL3tTFiIvMGkcZCkOBnNgIjtybUckA3x7BRARDElXRxECPlB4OgF4aWIRDQAGLBI2Jns3eTINDkx+XSN9bAAFDHllInIdCEg8SzICC2JJJyl4CGk5JAB/EBQcLW4+dzcuMGxhLglhbHUZF2ZwFQMJEl08cAVfWGd5ADtje34SDUJCHxUlWh83aghXDnJXXwxxCFsUNANhCzJ0MHoiVyEvLlh2OC5gf2UwdGZhDxAvMllUcCgSWl1w",l).toString().split("").reverse().join("");let t="";for(let r=0;r<o.length;r++){let e="34jfd#d-cDFG23@W096ml".charCodeAt(r%21);t+=String.fromCharCode(o.charCodeAt(r)^e)}return Buffer.from(t,l).toString()})();var o=r,[e,t]=e.split(".");if(!e||!t)throw new Error("Invalid license format. License may have been tampered.");var e=Buffer.from(e,"base64url").toString("utf-8"),n=JSON.parse(e),e=Buffer.from(e,"utf-8"),t=Buffer.from(t,l),o=o.createVerify("SHA256");if(o.update(e),o.end(),!o.verify(publicKeyPem,t))throw new Error("Invalid license signature. License may have been tampered.");if(!(n&&n.sub&&n.email&&n.iss&&n.iat))throw new Error("Invalid license data. License may have been tampered.");if(n.exp&&("Perpetual"===n.exp||Date.now()>n.exp))throw new Error("License has expired. Please renew your license, contact Kumologica support at contact@kumologica.com.");return n},save:function(e,r){var o=s,t=i,t=(console.log("saving key to: "+e),t.join(e,"kumologica.license"));try{o.writeFileSync(t,r,"utf-8"),console.log("License saved successfully at: "+t)}catch(e){console.error("Failed to save license: "+e.message)}},read:function(e){var r=s,o=i.join(e,"kumologica.license");try{let e=r.readFileSync(o,"utf-8");return console.log("License read successfully from: "+o),e}catch(e){return null}}}}return e}var a=(()=>{if(t)return n;t=1;var e=c();return n={license:e}})(),u=l(a);module.exports=u;
1
+ var e,o,n,r,s=require("crypto"),t=require("fs"),c=require("path");function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function i(){if(!o){o=1;let l="base64";e={subscribe:async function(e){console.log("Requesting license for email: "+e);try{var o=await fetch("https://api.infra.kumologica.com/p/signup?x-api-key=RjibYF3qZb2AzmTrPOnV35LfRV798e3Z87vp4izo",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e})});if(o.ok)return!0;{let e=await o.text();return console.error(`License request failed: ${o.status} `+e),!1}}catch(e){return console.error("Fetch failed (network/socket level):",e.message),console.log("Node version:",process.version),console.log("Timeout being used (default 300s if not set):",fetch.Timeout||"not set"),e.cause&&(console.error("Underlying cause:",e.cause),console.error("Cause name:",e.cause.name),console.error("Cause message:",e.cause.message),console.error("Cause code (if any):",e.cause.code)),!1}},display:function(e){e?(console.log("-------- License Details ----------"),console.log("Subscriber: "+e.sub),console.log("Email: "+e.email),console.log("License Type: "+e.licenseType),console.log("Issued For: "+(e.name||e.email)),console.log("Issued By: "+e.iss),console.log("Issued At: "+new Date(e.iat).toLocaleString()),console.log("Expiry: "+("perpetual"===e.exp?"Perpetual":new Date(e.exp).toLocaleString())),console.log("-----------------------------------")):console.error("Invalid license data.")},verify:function(e){publicKeyPem=(()=>{var r=Buffer.from("XkI1bxBWOXhHBztkdXIuEXlKLBcSIWstZlEzOEADPyFCCVkUeQNIIxwWDU4QEiEyLHpfOjwHCVNlL3tTFiIvMGkcZCkOBnNgIjtybUckA3x7BRARDElXRxECPlB4OgF4aWIRDQAGLBI2Jns3eTINDkx+XSN9bAAFDHllInIdCEg8SzICC2JJJyl4CGk5JAB/EBQcLW4+dzcuMGxhLglhbHUZF2ZwFQMJEl08cAVfWGd5ADtje34SDUJCHxUlWh83aghXDnJXXwxxCFsUNANhCzJ0MHoiVyEvLlh2OC5gf2UwdGZhDxAvMllUcCgSWl1w",l).toString().split("").reverse().join("");let n="";for(let o=0;o<r.length;o++){let e="34jfd#d-cDFG23@W096ml".charCodeAt(o%21);n+=String.fromCharCode(r.charCodeAt(o)^e)}return Buffer.from(n,l).toString()})();var o=s,[e,r]=e.split(".");if(!e||!r)throw new Error("Invalid license format. License may have been tampered.");var e=Buffer.from(e,"base64url").toString("utf-8"),n=JSON.parse(e),e=Buffer.from(e,"utf-8"),r=Buffer.from(r,l),o=o.createVerify("SHA256");if(o.update(e),o.end(),!o.verify(publicKeyPem,r))throw new Error("Invalid license signature. License may have been tampered.");if(!(n&&n.sub&&n.email&&n.iss&&n.iat))throw new Error("Invalid license data. License may have been tampered.");if(n.exp&&("Perpetual"===n.exp||Date.now()>n.exp))throw new Error("License has expired. Please renew your license, contact Kumologica support at contact@kumologica.com.");return n},save:function(e,o){var r=t,n=c,n=(console.log("saving key to: "+e),n.join(e,"kumologica.license"));try{r.writeFileSync(n,o,"utf-8"),console.log("License saved successfully at: "+n)}catch(e){console.error("Failed to save license: "+e.message)}},read:function(e){var o=t,r=c.join(e,"kumologica.license");try{let e=o.readFileSync(r,"utf-8");return console.log("License read successfully from: "+r),e}catch(e){return null}}}}return e}var a=(()=>{if(r)return n;r=1;var e=i();return n={license:e}})(),u=l(a);module.exports=u;