cloving 0.1.23 → 0.1.24

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.
@@ -64,7 +64,8 @@ Enumerate all the files in the provided list${gitDiff ? ' and git diff' : ''} as
64
64
  Also, list any test files that might be relevant to these files.`;
65
65
  };
66
66
  const handleUserAction = async (analysis, autoSave = false) => {
67
- const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(analysis);
67
+ const fileContents = (0, string_utils_1.extractFilesAndContent)(analysis);
68
+ const files = Object.keys(fileContents);
68
69
  if (autoSave) {
69
70
  for (const file of files) {
70
71
  if (fileContents[file]) {
@@ -147,9 +147,9 @@ class ChatManager {
147
147
  async handleSave() {
148
148
  const lastResponse = this.chatHistory.filter(msg => msg.role === 'assistant').pop();
149
149
  if (lastResponse) {
150
- const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(lastResponse.content);
151
- if (files.length > 0) {
152
- await (0, string_utils_1.saveGeneratedFiles)(files, fileContents);
150
+ const fileContents = (0, string_utils_1.extractFilesAndContent)(lastResponse.content);
151
+ if (Object.keys(fileContents).length > 0) {
152
+ await (0, string_utils_1.saveGeneratedFiles)(fileContents);
153
153
  console.info('Files have been saved.');
154
154
  }
155
155
  else {
@@ -99,18 +99,19 @@ Do not use any data from the example response structure, only use the structure.
99
99
  }
100
100
  });
101
101
  }
102
- async updateContextFiles(files, fileContents) {
103
- for (const file of files) {
102
+ async updateContextFiles(fileContents) {
103
+ for (const file of Object.keys(fileContents)) {
104
104
  if (fileContents[file]) {
105
105
  this.contextFiles[file] = fileContents[file];
106
106
  }
107
107
  }
108
108
  }
109
109
  async handleUserAction(rawCodeCommand, prompt) {
110
- const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
110
+ const fileContents = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
111
+ const files = Object.keys(fileContents);
111
112
  if (this.options.save) {
112
- await (0, string_utils_1.saveGeneratedFiles)(files, fileContents);
113
- await this.updateContextFiles(files, fileContents);
113
+ await (0, string_utils_1.saveGeneratedFiles)(fileContents);
114
+ await this.updateContextFiles(fileContents);
114
115
  return;
115
116
  }
116
117
  const action = await (0, prompts_1.select)({
@@ -190,7 +191,7 @@ Do not use any data from the example response structure, only use the structure.
190
191
  await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
191
192
  await fs_1.default.promises.writeFile(filePath, fileContents[fileToSave]);
192
193
  console.log(`${fileToSave} has been saved.`);
193
- await this.updateContextFiles([fileToSave], fileContents);
194
+ await this.updateContextFiles({ [fileToSave]: fileContents[fileToSave] });
194
195
  }
195
196
  else {
196
197
  console.log('File content not found.');
@@ -203,8 +204,8 @@ Do not use any data from the example response structure, only use the structure.
203
204
  }
204
205
  break;
205
206
  case 'saveAll':
206
- await (0, string_utils_1.saveGeneratedFiles)(files, fileContents);
207
- await this.updateContextFiles(files, fileContents);
207
+ await (0, string_utils_1.saveGeneratedFiles)(fileContents);
208
+ await this.updateContextFiles(fileContents);
208
209
  console.log('All files have been saved.');
209
210
  break;
210
211
  case 'done':
@@ -268,9 +269,9 @@ Please briefly explain how the code works in this.`;
268
269
  let rawCodeCommand = await this.generateCode(prompt);
269
270
  this.displayGeneratedCode(rawCodeCommand);
270
271
  if (this.options.save) {
271
- const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
272
- await (0, string_utils_1.saveGeneratedFiles)(files, fileContents);
273
- await this.updateContextFiles(files, fileContents);
272
+ const fileContents = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
273
+ await (0, string_utils_1.saveGeneratedFiles)(fileContents);
274
+ await this.updateContextFiles(fileContents);
274
275
  }
275
276
  else {
276
277
  await this.handleUserAction(rawCodeCommand, prompt);
@@ -300,9 +301,9 @@ Please briefly explain how the code works in this.`;
300
301
  rawCodeCommand = await this.generateCode(newPrompt, rawCodeCommand);
301
302
  this.displayGeneratedCode(rawCodeCommand);
302
303
  if (this.options.save || this.options.interactive) {
303
- const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
304
- await (0, string_utils_1.saveGeneratedFiles)(files, fileContents);
305
- await this.updateContextFiles(files, fileContents);
304
+ const fileContents = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
305
+ await (0, string_utils_1.saveGeneratedFiles)(fileContents);
306
+ await this.updateContextFiles(fileContents);
306
307
  }
307
308
  else {
308
309
  await this.handleUserAction(rawCodeCommand, newPrompt);
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloving",
3
- "version": "0.1.20",
3
+ "version": "0.1.23",
4
4
  "packageManager": "yarn@1.22.22",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,6 +49,7 @@
49
49
  "eslint-plugin-jsdoc": "^48.11.0",
50
50
  "eslint-plugin-n": "^17.10.1",
51
51
  "eslint-plugin-promise": "^7.0.0",
52
+ "express": "^4.19.2",
52
53
  "ignore": "^5.3.1",
53
54
  "ini": "^4.1.3",
54
55
  "isbinaryfile": "^5.0.2",
@@ -57,7 +58,9 @@
57
58
  "vite-node": "^2.0.5"
58
59
  },
59
60
  "devDependencies": {
61
+ "@types/body-parser": "^1.19.5",
60
62
  "@types/copy-paste": "^1.1.33",
63
+ "@types/express": "^4.17.21",
61
64
  "@types/ini": "^4.1.1",
62
65
  "@types/inquirer": "^9.0.7",
63
66
  "@types/jest": "^29.5.12",
@@ -98,30 +98,59 @@ const parseMarkdownInstructions = (input) => {
98
98
  exports.parseMarkdownInstructions = parseMarkdownInstructions;
99
99
  const extractFilesAndContent = (rawCodeCommand) => {
100
100
  if (!rawCodeCommand)
101
- return [[], {}];
101
+ return {};
102
102
  const files = [];
103
103
  const fileContents = {};
104
- const matches = rawCodeCommand.match(/(\*{2})([^\*]+)(\*{2})/g);
105
- if (!matches)
106
- return [files, fileContents];
107
- for (const match of matches) {
108
- const fileName = match.replace(/\*{2}/g, '').trim();
109
- const escapedFileName = fileName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
110
- const regex = new RegExp(`\\*\\*${escapedFileName}\\*\\*\\n\\n\\\`{3}([\\s\\S]+?)\\\`{3}(\n|$)`, 'g');
111
- const contentMatch = regex.exec(rawCodeCommand);
112
- if (contentMatch) {
113
- files.push(fileName);
114
- let content = contentMatch[1];
115
- // Remove the first word after the opening triple backticks
116
- content = content.split('\n').map((line, idx) => idx === 0 ? line.replace(/^\w+\s*/, '') : line).join('\n');
117
- fileContents[fileName] = content.trim();
104
+ let currentIndex = 0;
105
+ const commandLength = rawCodeCommand.length;
106
+ while (currentIndex < commandLength) {
107
+ let fileNameStart = rawCodeCommand.indexOf('**', currentIndex);
108
+ if (fileNameStart === -1)
109
+ break;
110
+ let fileNameEnd = rawCodeCommand.indexOf('**', fileNameStart + 2);
111
+ if (fileNameEnd === -1)
112
+ break;
113
+ let nextBoldStart = rawCodeCommand.indexOf('**', fileNameEnd + 2);
114
+ let nextCodeStart = rawCodeCommand.indexOf('\n```', fileNameEnd + 2);
115
+ while (nextBoldStart !== -1 && nextCodeStart > nextBoldStart) {
116
+ fileNameStart = nextBoldStart;
117
+ fileNameEnd = rawCodeCommand.indexOf('**', fileNameStart + 2);
118
+ nextBoldStart = rawCodeCommand.indexOf('**', fileNameEnd + 2);
119
+ nextCodeStart = rawCodeCommand.indexOf('\n```', fileNameEnd + 2);
118
120
  }
121
+ const fileName = rawCodeCommand.slice(fileNameStart + 2, fileNameEnd).trim();
122
+ files.push(fileName);
123
+ const codeBlockStart = rawCodeCommand.indexOf('\n```', fileNameEnd);
124
+ if (codeBlockStart === -1)
125
+ break;
126
+ let codeBlockEnd = codeBlockStart + 4;
127
+ while (codeBlockEnd < commandLength) {
128
+ if (rawCodeCommand.slice(codeBlockEnd, codeBlockEnd + 5) === '\n```\n') {
129
+ break;
130
+ }
131
+ else if (rawCodeCommand.slice(codeBlockEnd, codeBlockEnd + 4) === '\n```' && codeBlockEnd + 4 === commandLength) {
132
+ break;
133
+ }
134
+ codeBlockEnd++;
135
+ }
136
+ if (codeBlockEnd >= commandLength)
137
+ break;
138
+ let content = rawCodeCommand.slice(codeBlockStart + 4, codeBlockEnd).trim();
139
+ const firstNewlineIndex = content.indexOf('\n');
140
+ if (firstNewlineIndex !== -1) {
141
+ content = content.slice(firstNewlineIndex + 1);
142
+ }
143
+ else {
144
+ content = content.replace(/^\w+\s*/, '');
145
+ }
146
+ fileContents[fileName] = content.trim();
147
+ currentIndex = codeBlockEnd + 5;
119
148
  }
120
- return [files, fileContents];
149
+ return fileContents;
121
150
  };
122
151
  exports.extractFilesAndContent = extractFilesAndContent;
123
- const saveGeneratedFiles = async (files, fileContents) => {
124
- for (const file of files) {
152
+ const saveGeneratedFiles = async (fileContents) => {
153
+ for (const file of Object.keys(fileContents)) {
125
154
  if (fileContents[file]) {
126
155
  const filePath = path_1.default.resolve(file);
127
156
  await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloving",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "packageManager": "yarn@1.22.22",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",