@proteinjs/conversation 1.0.6 → 1.0.8

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.
Files changed (109) hide show
  1. package/.eslintrc.js +20 -0
  2. package/.prettierignore +4 -0
  3. package/.prettierrc +8 -0
  4. package/CHANGELOG.md +18 -4
  5. package/LICENSE +21 -0
  6. package/dist/src/CodegenConversation.d.ts.map +1 -1
  7. package/dist/src/CodegenConversation.js +2 -2
  8. package/dist/src/CodegenConversation.js.map +1 -1
  9. package/dist/src/Conversation.d.ts.map +1 -1
  10. package/dist/src/Conversation.js +33 -17
  11. package/dist/src/Conversation.js.map +1 -1
  12. package/dist/src/Function.d.ts.map +1 -1
  13. package/dist/src/OpenAi.d.ts.map +1 -1
  14. package/dist/src/OpenAi.js +55 -38
  15. package/dist/src/OpenAi.js.map +1 -1
  16. package/dist/src/Paragraph.d.ts.map +1 -1
  17. package/dist/src/Paragraph.js +2 -1
  18. package/dist/src/Paragraph.js.map +1 -1
  19. package/dist/src/Sentence.d.ts.map +1 -1
  20. package/dist/src/Sentence.js +4 -2
  21. package/dist/src/Sentence.js.map +1 -1
  22. package/dist/src/code_template/Code.d.ts.map +1 -1
  23. package/dist/src/code_template/Code.js +6 -2
  24. package/dist/src/code_template/Code.js.map +1 -1
  25. package/dist/src/code_template/CodeTemplate.d.ts.map +1 -1
  26. package/dist/src/code_template/CodeTemplate.js +2 -1
  27. package/dist/src/code_template/CodeTemplate.js.map +1 -1
  28. package/dist/src/code_template/Repo.d.ts.map +1 -1
  29. package/dist/src/code_template/Repo.js +8 -4
  30. package/dist/src/code_template/Repo.js.map +1 -1
  31. package/dist/src/fs/conversation_fs/ConversationFsModerator.d.ts.map +1 -1
  32. package/dist/src/fs/conversation_fs/ConversationFsModerator.js +18 -7
  33. package/dist/src/fs/conversation_fs/ConversationFsModerator.js.map +1 -1
  34. package/dist/src/fs/conversation_fs/ConversationFsModule.d.ts.map +1 -1
  35. package/dist/src/fs/conversation_fs/ConversationFsModule.js +1 -3
  36. package/dist/src/fs/conversation_fs/ConversationFsModule.js.map +1 -1
  37. package/dist/src/fs/conversation_fs/FsFunctions.d.ts.map +1 -1
  38. package/dist/src/fs/conversation_fs/FsFunctions.js +15 -29
  39. package/dist/src/fs/conversation_fs/FsFunctions.js.map +1 -1
  40. package/dist/src/fs/git/GitModule.d.ts.map +1 -1
  41. package/dist/src/fs/git/GitModule.js.map +1 -1
  42. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexFunctions.d.ts.map +1 -1
  43. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexFunctions.js +2 -2
  44. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexFunctions.js.map +1 -1
  45. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexModule.d.ts.map +1 -1
  46. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexModule.js +1 -3
  47. package/dist/src/fs/keyword_to_files_index/KeywordToFilesIndexModule.js.map +1 -1
  48. package/dist/src/fs/package/PackageFunctions.d.ts.map +1 -1
  49. package/dist/src/fs/package/PackageFunctions.js +20 -30
  50. package/dist/src/fs/package/PackageFunctions.js.map +1 -1
  51. package/dist/src/fs/package/PackageModule.d.ts.map +1 -1
  52. package/dist/src/fs/package/PackageModule.js +15 -8
  53. package/dist/src/fs/package/PackageModule.js.map +1 -1
  54. package/dist/src/history/MessageHistory.d.ts.map +1 -1
  55. package/dist/src/history/MessageHistory.js +6 -3
  56. package/dist/src/history/MessageHistory.js.map +1 -1
  57. package/dist/src/template/ConversationTemplate.d.ts.map +1 -1
  58. package/dist/src/template/ConversationTemplateFunctions.d.ts.map +1 -1
  59. package/dist/src/template/ConversationTemplateFunctions.js +2 -2
  60. package/dist/src/template/ConversationTemplateFunctions.js.map +1 -1
  61. package/dist/src/template/ConversationTemplateModule.d.ts.map +1 -1
  62. package/dist/src/template/ConversationTemplateModule.js +9 -7
  63. package/dist/src/template/ConversationTemplateModule.js.map +1 -1
  64. package/dist/src/template/createCode/CreateCodeConversationTemplate.d.ts.map +1 -1
  65. package/dist/src/template/createCode/CreateCodeConversationTemplate.js +2 -9
  66. package/dist/src/template/createCode/CreateCodeConversationTemplate.js.map +1 -1
  67. package/dist/src/template/createPackage/CreatePackageConversationTemplate.d.ts.map +1 -1
  68. package/dist/src/template/createPackage/CreatePackageConversationTemplate.js +1 -8
  69. package/dist/src/template/createPackage/CreatePackageConversationTemplate.js.map +1 -1
  70. package/dist/test/createKeywordFilesIndex.test.js.map +1 -1
  71. package/dist/test/openai/openai.generateList.test.js.map +1 -1
  72. package/dist/test/openai/openai.parseCodeFromMarkdown.test.js +7 -3
  73. package/dist/test/openai/openai.parseCodeFromMarkdown.test.js.map +1 -1
  74. package/dist/test/repo/repo.test.js.map +1 -1
  75. package/jest.config.js +2 -2
  76. package/package.json +9 -3
  77. package/src/CodegenConversation.ts +6 -4
  78. package/src/Conversation.ts +102 -33
  79. package/src/ConversationModule.ts +2 -2
  80. package/src/Function.ts +0 -1
  81. package/src/OpenAi.ts +128 -63
  82. package/src/Paragraph.ts +3 -2
  83. package/src/Sentence.ts +5 -3
  84. package/src/code_template/Code.ts +25 -19
  85. package/src/code_template/CodeTemplate.ts +8 -7
  86. package/src/code_template/CodeTemplateModule.ts +2 -2
  87. package/src/code_template/Repo.ts +25 -19
  88. package/src/fs/conversation_fs/ConversationFsModerator.ts +34 -20
  89. package/src/fs/conversation_fs/ConversationFsModule.ts +13 -7
  90. package/src/fs/conversation_fs/FsFunctions.ts +33 -44
  91. package/src/fs/git/GitModule.ts +2 -4
  92. package/src/fs/keyword_to_files_index/KeywordToFilesIndexFunctions.ts +31 -31
  93. package/src/fs/keyword_to_files_index/KeywordToFilesIndexModule.ts +19 -18
  94. package/src/fs/package/PackageFunctions.ts +34 -41
  95. package/src/fs/package/PackageModule.ts +33 -21
  96. package/src/history/MessageHistory.ts +7 -4
  97. package/src/history/MessageModerator.ts +1 -1
  98. package/src/template/ConversationTemplate.ts +9 -9
  99. package/src/template/ConversationTemplateFunctions.ts +8 -7
  100. package/src/template/ConversationTemplateModule.ts +24 -15
  101. package/src/template/createApp/CreateAppTemplate.ts +1 -1
  102. package/src/template/createCode/CreateCodeConversationTemplate.ts +9 -11
  103. package/src/template/createPackage/CreatePackageConversationTemplate.ts +2 -9
  104. package/src/template/createPackage/jest.config.js +2 -2
  105. package/test/createKeywordFilesIndex.test.ts +3 -3
  106. package/test/openai/openai.generateList.test.ts +5 -3
  107. package/test/openai/openai.parseCodeFromMarkdown.test.ts +10 -5
  108. package/test/repo/repo.test.ts +3 -4
  109. package/tsconfig.json +16 -20
@@ -10,7 +10,7 @@ import { TiktokenModel, encoding_for_model } from 'tiktoken';
10
10
  import { searchLibrariesFunctionName } from './fs/package/PackageFunctions';
11
11
 
12
12
  export type ConversationParams = {
13
- name: string,
13
+ name: string;
14
14
  modules?: ConversationModule[];
15
15
  logLevel?: LogLevel;
16
16
  limits?: {
@@ -18,7 +18,7 @@ export type ConversationParams = {
18
18
  maxMessagesInHistory?: number;
19
19
  tokenLimit?: number;
20
20
  };
21
- }
21
+ };
22
22
 
23
23
  export class Conversation {
24
24
  private tokenLimit = 3000;
@@ -33,26 +33,30 @@ export class Conversation {
33
33
 
34
34
  constructor(params: ConversationParams) {
35
35
  this.params = params;
36
- this.history = new MessageHistory({ maxMessages: params.limits?.maxMessagesInHistory, enforceMessageLimit: params.limits?.enforceLimits });
36
+ this.history = new MessageHistory({
37
+ maxMessages: params.limits?.maxMessagesInHistory,
38
+ enforceMessageLimit: params.limits?.enforceLimits,
39
+ });
37
40
  this.logger = new Logger(params.name, params.logLevel);
38
41
 
39
- if (params.modules)
42
+ if (params.modules) {
40
43
  this.addModules(params.modules);
44
+ }
41
45
 
42
46
  if (typeof params.limits?.enforceLimits === 'undefined' || params.limits.enforceLimits) {
43
- this.addFunctions('Conversation', [
44
- summarizeConversationHistoryFunction(this),
45
- ]);
47
+ this.addFunctions('Conversation', [summarizeConversationHistoryFunction(this)]);
46
48
  }
47
49
 
48
- if (params.limits?.tokenLimit)
50
+ if (params.limits?.tokenLimit) {
49
51
  this.tokenLimit = params.limits.tokenLimit;
52
+ }
50
53
  }
51
54
 
52
55
  private addModules(modules: ConversationModule[]) {
53
- for (let module of modules) {
54
- if (module.getSystemMessages().length < 1)
56
+ for (const module of modules) {
57
+ if (module.getSystemMessages().length < 1) {
55
58
  continue;
59
+ }
56
60
 
57
61
  this.addSystemMessagesToHistory([
58
62
  `The following are instructions from the ${module.getName()} module: ${module.getSystemMessages().join('. ')}`,
@@ -66,10 +70,11 @@ export class Conversation {
66
70
  this.functions.push(...functions);
67
71
  let functionInstructions = `The following are instructions from functions in the ${moduleName} module:`;
68
72
  let functionInstructionsAdded = false;
69
- for (let f of functions) {
73
+ for (const f of functions) {
70
74
  if (f.instructions) {
71
- if (!f.instructions || f.instructions.length < 1)
75
+ if (!f.instructions || f.instructions.length < 1) {
72
76
  continue;
77
+ }
73
78
 
74
79
  functionInstructionsAdded = true;
75
80
  const instructionsParagraph = f.instructions.join('. ');
@@ -77,8 +82,9 @@ export class Conversation {
77
82
  }
78
83
  }
79
84
 
80
- if (!functionInstructionsAdded)
85
+ if (!functionInstructionsAdded) {
81
86
  return;
87
+ }
82
88
 
83
89
  this.addSystemMessagesToHistory([functionInstructions]);
84
90
  }
@@ -88,21 +94,37 @@ export class Conversation {
88
94
  }
89
95
 
90
96
  private async enforceTokenLimit(messages: string[], model?: TiktokenModel) {
91
- if (this.params.limits?.enforceLimits === false)
97
+ if (this.params.limits?.enforceLimits === false) {
92
98
  return;
93
-
99
+ }
100
+
94
101
  const resolvedModel = model ? model : DEFAULT_MODEL;
95
102
  const encoder = encoding_for_model(resolvedModel);
96
103
  const conversation = this.history.toString() + messages.join('. ');
97
104
  const encoded = encoder.encode(conversation);
98
105
  console.log(`current tokens: ${encoded.length}`);
99
- if (encoded.length < this.tokenLimit)
106
+ if (encoded.length < this.tokenLimit) {
100
107
  return;
108
+ }
101
109
 
102
110
  const summarizeConversationRequest = `First, call the ${summarizeConversationHistoryFunctionName} function`;
103
- await OpenAi.generateResponse([summarizeConversationRequest], model, this.history, this.functions, this.messageModerators, this.params.logLevel);
111
+ await OpenAi.generateResponse(
112
+ [summarizeConversationRequest],
113
+ model,
114
+ this.history,
115
+ this.functions,
116
+ this.messageModerators,
117
+ this.params.logLevel
118
+ );
104
119
  const referenceSummaryRequest = `If there's a file mentioned in the conversation summary, find and read the file to better respond to my next request. If that doesn't find anything, call the ${searchLibrariesFunctionName} function on other keywords in the conversation summary to find a file to read`;
105
- await OpenAi.generateResponse([referenceSummaryRequest], model, this.history, this.functions, this.messageModerators, this.params.logLevel);
120
+ await OpenAi.generateResponse(
121
+ [referenceSummaryRequest],
122
+ model,
123
+ this.history,
124
+ this.functions,
125
+ this.messageModerators,
126
+ this.params.logLevel
127
+ );
106
128
  }
107
129
 
108
130
  summarizeConversationHistory(summary: string) {
@@ -116,7 +138,9 @@ export class Conversation {
116
138
  }
117
139
 
118
140
  addSystemMessagesToHistory(messages: string[], unshift = false) {
119
- const chatCompletions: ChatCompletionMessageParam[] = messages.map(message => { return { role: 'system', content: message }});
141
+ const chatCompletions: ChatCompletionMessageParam[] = messages.map((message) => {
142
+ return { role: 'system', content: message };
143
+ });
120
144
  if (unshift) {
121
145
  this.history.getMessages().unshift(...chatCompletions);
122
146
  this.history.prune();
@@ -128,40 +152,66 @@ export class Conversation {
128
152
  }
129
153
 
130
154
  addAssistantMessagesToHistory(messages: string[], unshift = false) {
131
- const chatCompletions: ChatCompletionMessageParam[] = messages.map(message => { return { role: 'assistant', content: message }});
155
+ const chatCompletions: ChatCompletionMessageParam[] = messages.map((message) => {
156
+ return { role: 'assistant', content: message };
157
+ });
132
158
  if (unshift) {
133
159
  this.history.getMessages().unshift(...chatCompletions);
134
160
  this.history.prune();
135
- } else
161
+ } else {
136
162
  this.history.push(chatCompletions);
163
+ }
137
164
  }
138
165
 
139
166
  addUserMessagesToHistory(messages: string[], unshift = false) {
140
- const chatCompletions: ChatCompletionMessageParam[] = messages.map(message => { return { role: 'user', content: message }});
167
+ const chatCompletions: ChatCompletionMessageParam[] = messages.map((message) => {
168
+ return { role: 'user', content: message };
169
+ });
141
170
  if (unshift) {
142
171
  this.history.getMessages().unshift(...chatCompletions);
143
172
  this.history.prune();
144
- } else
173
+ } else {
145
174
  this.history.push(chatCompletions);
175
+ }
146
176
  }
147
177
 
148
178
  async generateResponse(messages: string[], model?: TiktokenModel) {
149
179
  await this.enforceTokenLimit(messages, model);
150
- return await OpenAi.generateResponse(messages, model, this.history, this.functions, this.messageModerators, this.params.logLevel);
180
+ return await OpenAi.generateResponse(
181
+ messages,
182
+ model,
183
+ this.history,
184
+ this.functions,
185
+ this.messageModerators,
186
+ this.params.logLevel
187
+ );
151
188
  }
152
189
 
153
190
  async generateCode(description: string[], model?: TiktokenModel) {
154
191
  this.logger.info(`Generating code for description:\n${description.join('\n')}`);
155
- const code = await OpenAi.generateCode(description, model, this.history, this.functions, this.messageModerators, !this.generatedCode, this.params.logLevel);
192
+ const code = await OpenAi.generateCode(
193
+ description,
194
+ model,
195
+ this.history,
196
+ this.functions,
197
+ this.messageModerators,
198
+ !this.generatedCode,
199
+ this.params.logLevel
200
+ );
156
201
  this.logger.info(`Generated code:\n${code.slice(0, 150)}${code.length > 150 ? '...' : ''}`);
157
202
  this.generatedCode = true;
158
203
  return code;
159
204
  }
160
205
 
161
- async updateCodeFromFile(codeToUpdateFilePath: string, dependencyCodeFilePaths: string[], description: string, model?: TiktokenModel) {
206
+ async updateCodeFromFile(
207
+ codeToUpdateFilePath: string,
208
+ dependencyCodeFilePaths: string[],
209
+ description: string,
210
+ model?: TiktokenModel
211
+ ) {
162
212
  const codeToUpdate = await Fs.readFile(codeToUpdateFilePath);
163
213
  let dependencyDescription = `Assume the following exists:\n`;
164
- for (let dependencyCodeFilePath of dependencyCodeFilePaths) {
214
+ for (const dependencyCodeFilePath of dependencyCodeFilePaths) {
165
215
  const dependencCode = await Fs.readFile(dependencyCodeFilePath);
166
216
  dependencyDescription += dependencCode + '\n\n';
167
217
  }
@@ -171,15 +221,34 @@ export class Conversation {
171
221
  }
172
222
 
173
223
  async updateCode(code: string, description: string, model?: TiktokenModel) {
174
- this.logger.info(`Updating code:\n${code.slice(0, 150)}${code.length > 150 ? '...' : ''}\nFrom description: ${description}`);
175
- const updatedCode = await OpenAi.updateCode(code, description, model, this.history, this.functions, this.messageModerators, !this.generatedCode, this.params.logLevel);
224
+ this.logger.info(
225
+ `Updating code:\n${code.slice(0, 150)}${code.length > 150 ? '...' : ''}\nFrom description: ${description}`
226
+ );
227
+ const updatedCode = await OpenAi.updateCode(
228
+ code,
229
+ description,
230
+ model,
231
+ this.history,
232
+ this.functions,
233
+ this.messageModerators,
234
+ !this.generatedCode,
235
+ this.params.logLevel
236
+ );
176
237
  this.logger.info(`Updated code:\n${updatedCode.slice(0, 150)}${updatedCode.length > 150 ? '...' : ''}`);
177
238
  this.generatedCode = true;
178
239
  return updatedCode;
179
240
  }
180
241
 
181
242
  async generateList(description: string[], model?: TiktokenModel) {
182
- const list = await OpenAi.generateList(description, model, this.history, this.functions, this.messageModerators, !this.generatedList, this.params.logLevel);
243
+ const list = await OpenAi.generateList(
244
+ description,
245
+ model,
246
+ this.history,
247
+ this.functions,
248
+ this.messageModerators,
249
+ !this.generatedList,
250
+ this.params.logLevel
251
+ );
183
252
  this.generatedList = true;
184
253
  return list;
185
254
  }
@@ -199,9 +268,9 @@ export const summarizeConversationHistoryFunction = (conversation: Conversation)
199
268
  description: 'A 1-3 sentence summary of the current chat history',
200
269
  },
201
270
  },
202
- required: ['summary']
271
+ required: ['summary'],
203
272
  },
204
273
  },
205
274
  call: async (params: { summary: string }) => conversation.summarizeConversationHistory(params.summary),
206
- }
207
- }
275
+ };
276
+ };
@@ -2,7 +2,7 @@ import { Function } from './Function';
2
2
  import { MessageModerator } from './history/MessageModerator';
3
3
 
4
4
  export interface ConversationModule {
5
- getName(): string,
5
+ getName(): string;
6
6
  getSystemMessages(): string[];
7
7
  getFunctions(): Function[];
8
8
  getMessageModerators(): MessageModerator[];
@@ -10,4 +10,4 @@ export interface ConversationModule {
10
10
 
11
11
  export interface ConversationModuleFactory {
12
12
  createModule(repoPath: string): Promise<ConversationModule>;
13
- }
13
+ }
package/src/Function.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { ChatCompletionCreateParams } from 'openai/resources/chat';
2
2
 
3
-
4
3
  export interface Function {
5
4
  definition: ChatCompletionCreateParams.Function;
6
5
  call(obj: any): Promise<any>;
package/src/OpenAi.ts CHANGED
@@ -7,26 +7,38 @@ import { MessageHistory } from './history/MessageHistory';
7
7
  import { TiktokenModel } from 'tiktoken';
8
8
 
9
9
  function delay(ms: number) {
10
- return new Promise(resolve => setTimeout(resolve, ms));
10
+ return new Promise((resolve) => setTimeout(resolve, ms));
11
11
  }
12
12
 
13
13
  export const DEFAULT_MODEL: TiktokenModel = 'gpt-3.5-turbo';
14
14
  export class OpenAi {
15
- static async generateResponse(messages: string[], model?: string, history?: MessageHistory, functions?: Function[], messageModerators?: MessageModerator[], logLevel: LogLevel = 'info'): Promise<string> {
15
+ static async generateResponse(
16
+ messages: string[],
17
+ model?: string,
18
+ history?: MessageHistory,
19
+ functions?: Function[],
20
+ messageModerators?: MessageModerator[],
21
+ logLevel: LogLevel = 'info'
22
+ ): Promise<string> {
16
23
  const logger = new Logger('OpenAi.generateResponse', logLevel);
17
- const messageParams: ChatCompletionMessageParam[] = messages.map(message => { return { role: 'user', content: message }});
18
- if (history)
24
+ const messageParams: ChatCompletionMessageParam[] = messages.map((message) => {
25
+ return { role: 'user', content: message };
26
+ });
27
+ if (history) {
19
28
  history.push(messageParams);
29
+ }
20
30
  let messageParamsWithHistory = history ? history : new MessageHistory().push(messageParams);
21
- if (messageModerators)
31
+ if (messageModerators) {
22
32
  messageParamsWithHistory = OpenAi.moderateHistory(messageParamsWithHistory, messageModerators);
33
+ }
23
34
  const response = await OpenAi.executeRequest(messageParamsWithHistory, logLevel, functions, model);
24
35
  const responseMessage = response.choices[0].message;
25
36
  if (responseMessage.function_call) {
26
37
  messageParamsWithHistory.push([responseMessage]);
27
38
  const functionReturnMessage = await this.callFunction(logLevel, responseMessage.function_call, functions);
28
- if (functionReturnMessage)
29
- messageParamsWithHistory.push([functionReturnMessage])
39
+ if (functionReturnMessage) {
40
+ messageParamsWithHistory.push([functionReturnMessage]);
41
+ }
30
42
  return await this.generateResponse([], model, messageParamsWithHistory, functions, messageModerators, logLevel);
31
43
  }
32
44
 
@@ -41,50 +53,61 @@ export class OpenAi {
41
53
  }
42
54
 
43
55
  private static moderateHistory(history: MessageHistory, messageModerators: MessageModerator[]) {
44
- for (let messageModerator of messageModerators)
56
+ for (const messageModerator of messageModerators) {
45
57
  history.setMessages(messageModerator.observe(history.getMessages()));
58
+ }
46
59
 
47
60
  return history;
48
61
  }
49
62
 
50
- private static async executeRequest(messageParamsWithHistory: MessageHistory, logLevel: LogLevel, functions?: Function[], model?: string): Promise<ChatCompletion> {
63
+ private static async executeRequest(
64
+ messageParamsWithHistory: MessageHistory,
65
+ logLevel: LogLevel,
66
+ functions?: Function[],
67
+ model?: string
68
+ ): Promise<ChatCompletion> {
51
69
  const logger = new Logger('OpenAi.executeRequest', logLevel);
52
70
  const openaiApi = new OpenAIApi();
53
71
  let response: ChatCompletion;
54
72
  try {
55
73
  const latestMessage = messageParamsWithHistory.getMessages()[messageParamsWithHistory.getMessages().length - 1];
56
- if (latestMessage.content)
74
+ if (latestMessage.content) {
57
75
  logger.info(`Sending request: ${latestMessage.content}`);
58
- else if (latestMessage.role == 'function')
76
+ } else if (latestMessage.role == 'function') {
59
77
  logger.info(`Sending request: returning output of ${latestMessage.name} function`);
60
- else
78
+ } else {
61
79
  logger.info(`Sending request`);
80
+ }
62
81
  logger.debug(`Sending messages: ${JSON.stringify(messageParamsWithHistory.getMessages(), null, 2)}`, true);
63
82
  response = await openaiApi.chat.completions.create({
64
83
  model: model ? model : DEFAULT_MODEL,
65
84
  temperature: 0,
66
85
  messages: messageParamsWithHistory.getMessages(),
67
- functions: functions?.map(f => f.definition),
86
+ functions: functions?.map((f) => f.definition),
68
87
  });
69
88
  const responseMessage = response.choices[0].message;
70
- if (responseMessage.content)
89
+ if (responseMessage.content) {
71
90
  logger.info(`Received response: ${responseMessage.content}`);
72
- else if (responseMessage.function_call)
91
+ } else if (responseMessage.function_call) {
73
92
  logger.info(`Received response: call ${responseMessage.function_call.name} function`);
74
- else
93
+ } else {
75
94
  logger.info(`Received response`);
76
- if (response.usage)
95
+ }
96
+ if (response.usage) {
77
97
  logger.info(JSON.stringify(response.usage));
78
- else
98
+ } else {
79
99
  logger.info(JSON.stringify(`Usage data missing`));
80
- } catch(error: any) {
100
+ }
101
+ } catch (error: any) {
81
102
  logger.info(`Received error response, error type: ${error.type}`);
82
103
  if (typeof error.status !== 'undefined' && error.status == 429) {
83
104
  if (error.type == 'tokens' && typeof error.headers['x-ratelimit-reset-tokens'] === 'string') {
84
105
  const waitTime = parseInt(error.headers['x-ratelimit-reset-tokens']);
85
106
  const remainingTokens = error.headers['x-ratelimit-remaining-tokens'];
86
107
  const delayMs = 15000;
87
- logger.warn(`Waiting to retry in ${delayMs/1000}s, token reset in: ${waitTime}s, remaining tokens: ${remainingTokens}`);
108
+ logger.warn(
109
+ `Waiting to retry in ${delayMs / 1000}s, token reset in: ${waitTime}s, remaining tokens: ${remainingTokens}`
110
+ );
88
111
  await delay(delayMs);
89
112
  return await OpenAi.executeRequest(messageParamsWithHistory, logLevel, functions, model);
90
113
  }
@@ -96,21 +119,25 @@ export class OpenAi {
96
119
  return response;
97
120
  }
98
121
 
99
- private static async callFunction(logLevel: LogLevel, functionCall: ChatCompletionMessage.FunctionCall, functions?: Function[]): Promise<ChatCompletionMessageParam|undefined> {
122
+ private static async callFunction(
123
+ logLevel: LogLevel,
124
+ functionCall: ChatCompletionMessage.FunctionCall,
125
+ functions?: Function[]
126
+ ): Promise<ChatCompletionMessageParam | undefined> {
100
127
  const logger = new Logger('OpenAi.callFunction', logLevel);
101
128
  if (!functions) {
102
129
  const warning = `Assistant attempted to call a function when no functions were provided`;
103
130
  logger.warn(warning);
104
- const message: ChatCompletionMessageParam = { role: 'user', content: warning }
131
+ const message: ChatCompletionMessageParam = { role: 'user', content: warning };
105
132
  return message;
106
133
  }
107
134
 
108
135
  functionCall.name = functionCall.name.split('.').pop() as string;
109
- const f = functions.find(f => f.definition.name === functionCall.name);
136
+ const f = functions.find((f) => f.definition.name === functionCall.name);
110
137
  if (!f) {
111
138
  const warning = `Assistant attempted to call nonexistent function: ${functionCall.name}`;
112
139
  logger.warn(warning);
113
- const message: ChatCompletionMessageParam = { role: 'user', content: warning }
140
+ const message: ChatCompletionMessageParam = { role: 'user', content: warning };
114
141
  return message;
115
142
  }
116
143
 
@@ -118,46 +145,74 @@ export class OpenAi {
118
145
  try {
119
146
  logger.info(`Assistant calling function: ${f.definition.name}(${functionCall.arguments})`);
120
147
  returnObject = JSON.stringify(await f.call(JSON.parse(functionCall.arguments)));
121
- logger.info(`Assistant called function: ${f.definition.name}(${functionCall.arguments}) => ${returnObject}`, 1000);
148
+ logger.info(
149
+ `Assistant called function: ${f.definition.name}(${functionCall.arguments}) => ${returnObject}`,
150
+ 1000
151
+ );
122
152
  } catch (error: any) {
123
153
  logger.error(error.message);
124
154
  }
125
155
 
126
- if (!returnObject)
156
+ if (!returnObject) {
127
157
  return;
158
+ }
128
159
 
129
160
  return {
130
- role: 'function',
131
- name: f.definition.name,
161
+ role: 'function',
162
+ name: f.definition.name,
132
163
  content: returnObject,
133
164
  };
134
165
  }
135
166
 
136
- static async generateCode(messages: string[], model?: string, history?: MessageHistory, functions?: Function[], messageModerators?: MessageModerator[], includeSystemMessages: boolean = true, logLevel: LogLevel = 'info') {
167
+ static async generateCode(
168
+ messages: string[],
169
+ model?: string,
170
+ history?: MessageHistory,
171
+ functions?: Function[],
172
+ messageModerators?: MessageModerator[],
173
+ includeSystemMessages: boolean = true,
174
+ logLevel: LogLevel = 'info'
175
+ ) {
137
176
  const systemMessages: ChatCompletionMessageParam[] = [
138
- { role: 'system', content: 'Return only the code and exclude example usage, markdown, explanations, comments and notes.' },
177
+ {
178
+ role: 'system',
179
+ content: 'Return only the code and exclude example usage, markdown, explanations, comments and notes.',
180
+ },
139
181
  { role: 'system', content: `Write code in typescript.` },
140
182
  { role: 'system', content: `Declare explicit types for all function parameters.` },
141
183
  { role: 'system', content: 'Export all functions and objects generated.' },
142
184
  { role: 'system', content: 'Do not omit function implementations.' },
143
185
  ];
144
- const resolvedHistory = history ?
145
- includeSystemMessages ?
146
- history.push(systemMessages)
147
- :
148
- history
149
- :
150
- includeSystemMessages ?
151
- new MessageHistory().push(systemMessages)
152
- :
153
- undefined
154
- ;
186
+ const resolvedHistory = history
187
+ ? includeSystemMessages
188
+ ? history.push(systemMessages)
189
+ : history
190
+ : includeSystemMessages
191
+ ? new MessageHistory().push(systemMessages)
192
+ : undefined;
155
193
  const code = await this.generateResponse(messages, model, resolvedHistory, functions, messageModerators, logLevel);
156
194
  return this.parseCodeFromMarkdown(code);
157
195
  }
158
196
 
159
- static async updateCode(code: string, description: string, model?: string, history?: MessageHistory, functions?: Function[], messageModerators?: MessageModerator[], includeSystemMessages: boolean = true, logLevel: LogLevel = 'info') {
160
- return await this.generateCode([this.updateCodeDescription(code, description)], model, history, functions, messageModerators, includeSystemMessages, logLevel);
197
+ static async updateCode(
198
+ code: string,
199
+ description: string,
200
+ model?: string,
201
+ history?: MessageHistory,
202
+ functions?: Function[],
203
+ messageModerators?: MessageModerator[],
204
+ includeSystemMessages: boolean = true,
205
+ logLevel: LogLevel = 'info'
206
+ ) {
207
+ return await this.generateCode(
208
+ [this.updateCodeDescription(code, description)],
209
+ model,
210
+ history,
211
+ functions,
212
+ messageModerators,
213
+ includeSystemMessages,
214
+ logLevel
215
+ );
161
216
  }
162
217
 
163
218
  static updateCodeDescription(code: string, description: string) {
@@ -165,22 +220,25 @@ export class OpenAi {
165
220
  }
166
221
 
167
222
  static parseCodeFromMarkdown(code: string) {
168
- if (!code.match(/```([\s\S]+?)```/g))
223
+ if (!code.match(/```([\s\S]+?)```/g)) {
169
224
  return code;
225
+ }
170
226
 
171
227
  const filteredLines: string[] = [];
172
228
  let inCodeBlock = false;
173
- for (let line of code.split('\n')) {
229
+ for (const line of code.split('\n')) {
174
230
  if (line.startsWith('```')) {
175
231
  inCodeBlock = !inCodeBlock;
176
- if (!inCodeBlock)
232
+ if (!inCodeBlock) {
177
233
  filteredLines.push('');
178
-
234
+ }
235
+
179
236
  continue;
180
237
  }
181
238
 
182
- if (inCodeBlock)
239
+ if (inCodeBlock) {
183
240
  filteredLines.push(line);
241
+ }
184
242
  }
185
243
 
186
244
  // remove the last '' that will become a \n
@@ -190,23 +248,30 @@ export class OpenAi {
190
248
  return filteredLines.join('\n');
191
249
  }
192
250
 
193
- static async generateList(messages: string[], model?: string, history?: MessageHistory, functions?: Function[], messageModerators?: MessageModerator[], includeSystemMessages: boolean = true, logLevel: LogLevel = 'info'): Promise<string[]> {
251
+ static async generateList(
252
+ messages: string[],
253
+ model?: string,
254
+ history?: MessageHistory,
255
+ functions?: Function[],
256
+ messageModerators?: MessageModerator[],
257
+ includeSystemMessages: boolean = true,
258
+ logLevel: LogLevel = 'info'
259
+ ): Promise<string[]> {
194
260
  const systemMessages: ChatCompletionMessageParam[] = [
195
- { role: 'system', content: 'Return only the list and exclude example usage, markdown and all explanations, comments and notes.' },
261
+ {
262
+ role: 'system',
263
+ content: 'Return only the list and exclude example usage, markdown and all explanations, comments and notes.',
264
+ },
196
265
  { role: 'system', content: 'Separate each item in the list by a ;' },
197
266
  ];
198
- const resolvedHistory = history ?
199
- includeSystemMessages ?
200
- history.push(systemMessages)
201
- :
202
- history
203
- :
204
- includeSystemMessages ?
205
- new MessageHistory().push(systemMessages)
206
- :
207
- undefined
208
- ;
267
+ const resolvedHistory = history
268
+ ? includeSystemMessages
269
+ ? history.push(systemMessages)
270
+ : history
271
+ : includeSystemMessages
272
+ ? new MessageHistory().push(systemMessages)
273
+ : undefined;
209
274
  const list = await this.generateResponse(messages, model, resolvedHistory, functions, messageModerators, logLevel);
210
- return list.split(';').map(item => item.trim());
275
+ return list.split(';').map((item) => item.trim());
211
276
  }
212
- }
277
+ }
package/src/Paragraph.ts CHANGED
@@ -9,9 +9,10 @@ export class Paragraph {
9
9
  }
10
10
 
11
11
  toString(): string {
12
- if (this.sentences.length == 0)
12
+ if (this.sentences.length == 0) {
13
13
  return '';
14
+ }
14
15
 
15
16
  return this.sentences.join(' ');
16
17
  }
17
- }
18
+ }
package/src/Sentence.ts CHANGED
@@ -8,13 +8,15 @@ export class Sentence {
8
8
  }
9
9
 
10
10
  toString(): string {
11
- if (this.lines.length == 0)
11
+ if (this.lines.length == 0) {
12
12
  return '';
13
+ }
13
14
 
14
15
  let sentence = this.lines.join(', ');
15
- if (sentence.lastIndexOf('.') != (sentence.length - 1))
16
+ if (sentence.lastIndexOf('.') != sentence.length - 1) {
16
17
  sentence += '.';
18
+ }
17
19
 
18
20
  return sentence;
19
21
  }
20
- }
22
+ }