@kumologica/sdk 4.0.0-beta8 → 4.0.0-beta9

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,194 @@
1
+ // properties: ~/.kumologica/credentials
2
+
3
+ const defaultContent = `; This file contains all your sensitive credential information
4
+ ; about your ai configuration used by Kumologica Designer.
5
+ ; For more information visit https://docs.kumologica.com/settings
6
+ ;
7
+ ; supported providers: openai, anthropic, deepseek, xai, gemini, aws bedrock
8
+ ;
9
+ ; Examples:
10
+ ;
11
+ ; =============== Anthropic =======================
12
+ ; [anthropic-haiku]
13
+ ; provider = anthropic
14
+ ; model = claude-haiku-4-5
15
+ ; api_key = your-anthropic-api-key
16
+ ; max_tokens = 4096
17
+ ; temperature = 0.7
18
+
19
+ ; ============= OpenAI =======================
20
+ ; [openai-gpt4o]
21
+ ; provider = openai
22
+ ; model = gpt-4o
23
+ ; api_key = your-openai-api-key
24
+ ; max_tokens = 8192
25
+ ; temperature = 0.7
26
+
27
+ ; ============= AWS Bedrock =======================
28
+ ; [aws bedrock claude 3.5 sonnet]
29
+ ; provider = bedrock
30
+ ; model=anthropic.claude-3-5-sonnet-20241022-v2:0
31
+ ; region=ap-southeast-2
32
+ ; ; your local AWS profile name, if not provided the default profile will be used
33
+ ; profile=bedrock
34
+ ; max_tokens = 8192
35
+ ; temperature = 0.7
36
+ `
37
+
38
+ const os = require('os');
39
+ const fs = require('fs');
40
+ const fsx = require('fs-extra')
41
+ const ini = require('ini');
42
+ const path = require('path');
43
+ const got = require('got');
44
+
45
+ const PROMPT_URL = 'https://kumologica.com/ai/kumologica-prompt.md';
46
+ const FILENAME_PREFIX = 'kumologica-prompt';
47
+ const FILE_EXTENSION = '.md';
48
+ const MAX_AGE_DAYS = 7;
49
+
50
+ class AiConfigStore {
51
+ // aiConfigFileFullPath: a string representing the full path of the ai config file
52
+
53
+ constructor() {
54
+ let homedir = os.homedir();
55
+ const credsDir = '.kumologica';
56
+ const credsFile = `ai`;
57
+
58
+ this.aiConfigFileFullPath = path.join(homedir, credsDir, credsFile);
59
+ this.promptDirectory = path.join(homedir, credsDir);
60
+
61
+ // check whether the config file exist or not: ~/.kumologica/ai
62
+ if (!fs.existsSync(this.aiConfigFileFullPath)){
63
+ // create file and write default content on it
64
+ console.log(`Creating AI config file on: ${this.aiConfigFileFullPath}...`)
65
+ fsx.ensureDirSync(path.join(homedir, credsDir));
66
+ fs.writeFileSync(this.aiConfigFileFullPath, defaultContent);
67
+ }
68
+
69
+ this.initFile = this.parseAiConfigFile();
70
+ this.syncPrompt();
71
+ }
72
+
73
+ deleteOldFiles(files) {
74
+ for (const f of files) {
75
+ try {
76
+ fs.unlinkSync(f.fullPath);
77
+ console.debug(`Deleted old: ${f.name}`);
78
+ } catch {}
79
+ }
80
+ }
81
+
82
+ getPromptFiles() {
83
+ try {
84
+ return fs.readdirSync(this.promptDirectory)
85
+ .filter(f => f.startsWith(FILENAME_PREFIX) && f.endsWith(FILE_EXTENSION))
86
+ .map(f => {
87
+ const fullPath = path.join(this.promptDirectory, f);
88
+ try {
89
+ const stat = fs.statSync(fullPath);
90
+ return { name: f, fullPath, mtime: stat.mtime.getTime() };
91
+ } catch {
92
+ return null;
93
+ }
94
+ })
95
+ .filter(Boolean)
96
+ .sort((a, b) => b.mtime - a.mtime); // newest first
97
+ } catch {
98
+ return [];
99
+ }
100
+ }
101
+
102
+ getPrompt() {
103
+ if (this.prompt) {
104
+ return this.prompt;
105
+ }
106
+
107
+ const newest = this.getPromptFiles()[0];
108
+ if (!newest) return null;
109
+
110
+ try {
111
+ this.prompt = fs.readFileSync(newest.fullPath, 'utf-8').trim();
112
+ return this.prompt;
113
+ } catch (err) {
114
+ console.error('Failed to read prompt file:', err.message);
115
+ return null;
116
+ }
117
+ }
118
+
119
+
120
+ async syncPrompt() {
121
+ const files = this.getPromptFiles();
122
+ const newest = files[0] || null;
123
+
124
+ const isRecent = newest && (Date.now() - newest.mtime) <= MAX_AGE_DAYS * 24 * 60 * 60 * 1000;
125
+
126
+ if (isRecent) {
127
+ // Still fresh → just clean up any old junk and exit
128
+ this.deleteOldFiles(files.slice(1));
129
+ return;
130
+ }
131
+
132
+ // Need fresh copy
133
+ const filename = `${FILENAME_PREFIX}-${new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)}${FILE_EXTENSION}`;
134
+ const filepath = path.join(this.promptDirectory, filename);
135
+
136
+ try {
137
+ console.log('Downloading latest prompt...');
138
+ const { body } = await got(PROMPT_URL);
139
+ fs.writeFileSync(filepath, body, 'utf-8');
140
+ console.log(`Saved: ${filename}`);
141
+
142
+ // Delete everything except the new file
143
+ this.deleteOldFiles(files);
144
+ } catch (err) {
145
+ try { fs.unlinkSync(filepath); } catch {}
146
+ throw new Error(`Download failed: ${err.message}`);
147
+ }
148
+ }
149
+
150
+ getSections() {
151
+ return Object.keys(this.initFile).filter(key => key !== '');
152
+ }
153
+
154
+ parseAiConfigFile() {
155
+ this.initFile = ini.parse(this.readAiConfigFile());
156
+ return this.initFile;
157
+ }
158
+
159
+ getAliases(section){
160
+ if (this.initFile && this.initFile[section]){
161
+ return Object.keys(this.initFile[section]);
162
+ }else{
163
+ return null;
164
+ }
165
+ }
166
+
167
+ getAliasInfo(section, alias) {
168
+ if (this.initFile && this.initFile[section]){
169
+ return this.initFile[section][alias];
170
+ }else{
171
+ return null;
172
+ }
173
+ }
174
+
175
+ getAiConfigFileFullPath() {
176
+ return this.aiConfigFileFullPath;
177
+ }
178
+
179
+ writeAiConfigFile(content) {
180
+ this.initFile = ini.parse(content);
181
+ fs.writeFileSync(this.aiConfigFileFullPath, content);
182
+ }
183
+
184
+ readAiConfigFile() {
185
+ const data = fs.readFileSync(this.aiConfigFileFullPath, "utf-8");
186
+ const lines = data.split(/\r\n|\n/);
187
+
188
+ return lines.map(l => l.trim()).join('\n');
189
+ }
190
+ }
191
+
192
+ module.exports = {
193
+ AiConfigStore
194
+ };
@@ -35,8 +35,9 @@ const KumohubConfig = require("./lib/stores/kumohub-config-store");
35
35
  const AzureConfig = require("./lib/stores/azure-config-store");
36
36
  const ProjectInfoConfig = require("./lib/stores/project-info-config-store");
37
37
  const { CloudConfigStore } = require("./lib/stores/settings-cloud-store");
38
+ const { AiConfigStore } = require("./lib/stores/settings-ai-store");
38
39
  const { NetworkConfigStore } = require("./lib/stores/settings-network-store");
39
- const { OpenAIClient } = require("./lib/ai/openai");
40
+ const { chatAi } = require("./lib/ai/chatai");
40
41
 
41
42
  const AWSProfile = require("./lib/aws/aws-profile");
42
43
  const AWSDeployer = require("./lib/aws");
@@ -69,10 +70,9 @@ const KUMOLOGICA_NODE_LIB_BASEURL = "https://library.kumohub.io";
69
70
  const KUMOLOGICA_NODE_LIB_URL = `${KUMOLOGICA_NODE_LIB_BASEURL}/library.json`;
70
71
 
71
72
  const cloudConfigStore = new CloudConfigStore();
73
+ const aiConfigStore = new AiConfigStore();
72
74
  const networkConfigStore = new NetworkConfigStore();
73
75
 
74
- const openAIClient = new OpenAIClient({ version: "gpt-3.5-turbo" }); //'gpt-4'
75
-
76
76
  // function to be called each time
77
77
  // project changes - either new project created or old project opened.
78
78
  // header.js is the component handling project changes.
@@ -82,6 +82,7 @@ function loadConfigs() {
82
82
  window.__kumologica.settings.cloudConfig = new CloudConfig.CloudConfigStore({
83
83
  dataPath: window.__kumologica.settings.projectDir,
84
84
  });
85
+ window.__kumologica.settings.aiConfig = new AiConfigStore();
85
86
 
86
87
  window.__kumologica.settings.kumohubConfig =
87
88
  new KumohubConfig.KumohubConfigStore({
@@ -580,6 +581,11 @@ function includeNodePathIntoPath() {
580
581
  }
581
582
  }
582
583
 
584
+
585
+ async function chatWithAi(params) {
586
+ return await chatAi(params );
587
+ }
588
+
583
589
  async function npmInstall(dependency) {
584
590
  return new Promise((resolve, reject) => {
585
591
  window.__kumologica.editor.terminal.eventEmitter.emit(
@@ -679,6 +685,7 @@ window.__kumologica.settings = {};
679
685
  window.__kumologica.settings.loadConfigs = loadConfigs;
680
686
 
681
687
  window.__kumologica.settings.cloudConfigStore = cloudConfigStore;
688
+ window.__kumologica.settings.aiConfigStore = aiConfigStore;
682
689
  window.__kumologica.settings.networkConfigStore = networkConfigStore;
683
690
  window.__kumologica.settings.workspacePreferenceStore =
684
691
  new WorkspacePreferenceStore();
@@ -737,7 +744,8 @@ window.__kumologica.libs.dagre = dagre;
737
744
  window.__kumologica.libs.simpleGit = simpleGit;
738
745
 
739
746
  // AI utilities
740
- window.__kumologica.libs.openAIClient = openAIClient;
747
+ window.__kumologica.libs.chatAi = chatWithAi;
748
+
741
749
 
742
750
  /**
743
751
  * Return the name of the valid kumologica flow or undefined otherwise.