aimyapi 0.2.1 → 1.0.2
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/README.md +72 -310
- package/dist/index.cjs +332 -120
- package/dist/index.d.cts +32 -11
- package/dist/index.d.mts +32 -11
- package/dist/index.d.ts +32 -11
- package/dist/index.js +332 -120
- package/dist/index.mjs +332 -121
- package/example/example1.ts +11 -8
- package/example/example2.ts +31 -20
- package/example/example3.ts +25 -18
- package/example/ordering_api.md +21 -19
- package/example/ordering_api.ts +3 -2
- package/example/ordering_api_impl.ts +2 -1
- package/example/sales_api.md +3 -8
- package/example/sales_api.ts +2 -2
- package/example/sales_api_impl.ts +1 -1
- package/package.json +12 -10
- package/prompts/create-task-prompt.md +19 -21
- package/src/index.ts +324 -139
- package/src/sandbox.ts +119 -26
- package/tsconfig.json +1 -0
package/src/index.ts
CHANGED
|
@@ -3,177 +3,259 @@ import fs from 'fs';
|
|
|
3
3
|
import { OpenAI } from "openai";
|
|
4
4
|
import path from 'path';
|
|
5
5
|
|
|
6
|
-
import createSandbox from "./sandbox";
|
|
6
|
+
import createSandbox, { CodeRunResult } from "./sandbox";
|
|
7
7
|
import { rejectOpenPromises } from './sandbox-wrappers';
|
|
8
8
|
|
|
9
9
|
import { ChatCompletionMessageParam } from 'openai/resources/index.mjs';
|
|
10
10
|
import { QuickJSWASMModule, getQuickJS } from "quickjs-emscripten";
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import { AutoParseableTool } from 'openai/lib/parser.js';
|
|
13
|
+
import { ZodSchema, z } from 'zod';
|
|
14
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
import * as ApiDefs from 'api.ts'
|
|
16
|
+
const openai = new OpenAI();
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
try {`;
|
|
18
|
+
let QuickJS:QuickJSWASMModule | null = null;
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
export interface AIMyAPIOptions {
|
|
21
|
+
apiObject: object;
|
|
22
|
+
apiExports: object;
|
|
23
|
+
apiWhitelist?: string[]; // List of functions to expose to the user. Necessary to pass this yourself if you are extending your api from another class.
|
|
24
|
+
apiGlobals?: object;
|
|
25
|
+
apiDefFilePath: string; // Full path to the api definition file so that it can be loaded into the prompt
|
|
26
|
+
apiGlobalName?: string;
|
|
27
|
+
apiDocsPath?: string;
|
|
28
|
+
debug?: boolean;
|
|
29
|
+
model?: string;
|
|
30
|
+
additionalModelOptions?: object;
|
|
31
|
+
hideLogsFromAgent?: boolean; // If true, logs from code execution will not be included in the messages sent to the agent. This can be useful to prevent the agent from being overwhelmed with logs or to hide implementation details. Default is false (logs will be included in messages).
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface AIMyAPIInstance {
|
|
35
|
+
options:AIMyAPIOptions;
|
|
36
|
+
generateCode: (queryText:string, userChatHistory:ChatCompletionMessageParam[]) => Promise<GenerateCodeResult | null>;
|
|
37
|
+
runCode: (code:string) => Promise<CodeRunResult>;
|
|
38
|
+
checkCode: (code:string) => Promise<CodeRunResult>;
|
|
39
|
+
// run a single request with no history
|
|
40
|
+
processRequest: (userQuery:string, context?: object) => Promise<GenerateCodeResult | null>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface GenerateCodeResult {
|
|
44
|
+
code?: string;
|
|
45
|
+
comments?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
const wrapCode = (apiGlobalName:string, apiFileDefPath:string, code:string) => `
|
|
50
|
+
(async () => {
|
|
51
|
+
try {
|
|
52
|
+
${code}
|
|
53
|
+
} catch(err) {
|
|
23
54
|
console.error(err);
|
|
24
55
|
}
|
|
25
56
|
})();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const code = match.slice(3, -3).trim();
|
|
37
|
-
return `${CODE_START}\n${indentString(code, 2)}\n${CODE_END}`;
|
|
38
|
-
});
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
const wrapCodeBlock = (code:string, codeType:string = "") => `
|
|
60
|
+
\`\`\`${codeType}
|
|
61
|
+
${code}
|
|
62
|
+
\`\`\`
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
export function zodParseJSON<T>(schema: ZodSchema<T>) {
|
|
66
|
+
return (input: string): T => schema.parse(JSON.parse(input));
|
|
39
67
|
}
|
|
40
68
|
|
|
41
|
-
export function createBasePrompt(apiFilePath:string,
|
|
69
|
+
export function createBasePrompt(apiFilePath:string, apiGlobalName: string, documentationPath?: string, ): string {
|
|
42
70
|
const apiText: string = fs.readFileSync(apiFilePath, 'utf8');
|
|
43
71
|
const documentationText: string = documentationPath ? fs.readFileSync(documentationPath, 'utf8') : '';
|
|
44
72
|
|
|
45
73
|
//console.time("Loading templates");
|
|
46
|
-
const createTaskPrompt: string = fs.readFileSync( path.join(__dirname, '../prompts/create-task-prompt.md'), 'utf8').replace("{{DOCUMENTATION}}",
|
|
74
|
+
const createTaskPrompt: string = fs.readFileSync( path.join(__dirname, '../prompts/create-task-prompt.md'), 'utf8').replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
|
|
47
75
|
//console.timeEnd("Loading templates")
|
|
48
76
|
|
|
49
77
|
return createTaskPrompt;
|
|
50
78
|
}
|
|
51
79
|
|
|
52
|
-
export interface GenerateCodeResult {
|
|
53
|
-
code: string;
|
|
54
|
-
loggableCode: string;
|
|
55
|
-
rawResponse?: string;
|
|
56
|
-
}
|
|
57
80
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
const runCodeSchema = z.object({
|
|
82
|
+
code: z.string(),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const checkCodeSchema = z.object({
|
|
86
|
+
code: z.string(),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const submitCodeSchema = z.object({
|
|
90
|
+
code: z.string(),
|
|
91
|
+
});
|
|
62
92
|
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
export const generateCode = async function(instance:AIMyAPIInstance, queryText:string, userChatHistory:ChatCompletionMessageParam[], createTaskPrompt:string, debug:boolean = false, hideLogsFromAgent:boolean = false, model="gpt-5-mini", additionalModelOptions?: object): Promise<GenerateCodeResult | null> {
|
|
94
|
+
let finalSubmittedCode = "";
|
|
95
|
+
|
|
96
|
+
if(debug) {
|
|
97
|
+
console.log("Generating code for query:", queryText);
|
|
98
|
+
}
|
|
99
|
+
// checkcode
|
|
100
|
+
const codingTools: AutoParseableTool<any, true>[] = [
|
|
65
101
|
{
|
|
66
|
-
|
|
67
|
-
|
|
102
|
+
type: "function",
|
|
103
|
+
function: {
|
|
104
|
+
name: "runCode",
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
function: async ({code}: {code: string}) => {
|
|
107
|
+
if(debug) {
|
|
108
|
+
console.log("Running code...", code);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const res = await instance.runCode(code);
|
|
112
|
+
|
|
113
|
+
if(hideLogsFromAgent) {
|
|
114
|
+
res.logs = [];
|
|
115
|
+
}
|
|
116
|
+
return res;
|
|
117
|
+
},
|
|
118
|
+
description: "Run the provided code in a sandboxed environment. The code will have access to the API object. Returns the result of the code execution.",
|
|
119
|
+
parse: zodParseJSON(runCodeSchema),
|
|
120
|
+
parameters: zodToJsonSchema(runCodeSchema),
|
|
121
|
+
}
|
|
68
122
|
},
|
|
69
|
-
...userChatHistory,
|
|
70
123
|
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
124
|
+
type: "function",
|
|
125
|
+
function: {
|
|
126
|
+
name: "checkCode",
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
function: async ({code}: {code: string}) => {
|
|
129
|
+
if(debug) {
|
|
130
|
+
console.log("Checking code...", code);
|
|
131
|
+
}
|
|
132
|
+
const res = await instance.checkCode(code);
|
|
133
|
+
|
|
134
|
+
return res;
|
|
135
|
+
|
|
136
|
+
},
|
|
137
|
+
description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
|
|
138
|
+
parse: zodParseJSON(checkCodeSchema),
|
|
139
|
+
parameters: zodToJsonSchema(checkCodeSchema),
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: "function",
|
|
144
|
+
function: {
|
|
145
|
+
name: "submitCode",
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
function: async ({code}: {code: string}) => {
|
|
148
|
+
finalSubmittedCode = code;
|
|
149
|
+
return {
|
|
150
|
+
success: true,
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
description: "Submit the provided code as the final code to run. This will end the code generation process and the code will be run in the sandbox. Use this when you are confident in the code you have generated and want to run it.",
|
|
154
|
+
parse: zodParseJSON(submitCodeSchema),
|
|
155
|
+
parameters: zodToJsonSchema(submitCodeSchema),
|
|
156
|
+
}
|
|
74
157
|
}
|
|
75
158
|
];
|
|
76
159
|
|
|
77
160
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
161
|
+
|
|
162
|
+
const runner = openai.chat.completions
|
|
163
|
+
.runTools({
|
|
164
|
+
model,
|
|
165
|
+
messages: [
|
|
166
|
+
{
|
|
167
|
+
role: 'system',
|
|
168
|
+
content: "You will assist with writing code to perform the user's request.",
|
|
169
|
+
},
|
|
170
|
+
...userChatHistory,
|
|
171
|
+
{
|
|
172
|
+
role: 'user',
|
|
173
|
+
content: createTaskPrompt.replace("{{USER_QUERY}}", queryText)
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
],
|
|
177
|
+
tools: codingTools,
|
|
178
|
+
...additionalModelOptions,
|
|
179
|
+
|
|
180
|
+
})
|
|
181
|
+
.on('message', async (message: ChatCompletionMessageParam) => {
|
|
182
|
+
if(debug) {
|
|
183
|
+
console.log("Message:", JSON.stringify(message, null, 2));
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
.on('functionToolCall', (functionCall: OpenAI.Chat.Completions.ChatCompletionMessageFunctionToolCall.Function) => {
|
|
188
|
+
if(debug) {
|
|
189
|
+
console.log("Function Call:", JSON.stringify(functionCall, null, 2));
|
|
99
190
|
}
|
|
100
|
-
|
|
191
|
+
|
|
101
192
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
193
|
+
})
|
|
194
|
+
.on('functionToolCallResult', (functionCall) => {
|
|
195
|
+
if(debug) {
|
|
196
|
+
console.log("Function Call Result:", JSON.stringify(functionCall, null, 2));
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
const finalContent = await runner.finalContent();
|
|
201
|
+
|
|
202
|
+
if(debug) {
|
|
203
|
+
console.log("Final Content:", finalContent);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
code: finalSubmittedCode,
|
|
208
|
+
comments: finalContent || undefined,
|
|
209
|
+
}
|
|
106
210
|
|
|
107
|
-
if(debug)
|
|
108
|
-
console.log(response);
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const json = JSON.parse(response);
|
|
112
|
-
const code = json.yourCode.replaceAll('```', '');
|
|
113
|
-
|
|
114
|
-
return { code, loggableCode: code };
|
|
115
|
-
} catch(err) {
|
|
116
|
-
console.error("Error parsing response", err);
|
|
117
|
-
return { code: '', loggableCode: '' };
|
|
118
|
-
}
|
|
119
211
|
} catch(err) {
|
|
120
212
|
console.error(err);
|
|
121
|
-
return
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
let QuickJS:QuickJSWASMModule = null;
|
|
126
|
-
|
|
127
|
-
export interface AIMyAPIOptions {
|
|
128
|
-
apiObject: object;
|
|
129
|
-
apiExports: object;
|
|
130
|
-
apiWhitelist?: string[]; // List of functions to expose to the user. Necessary to pass this yourself if you are extending your api from another class.
|
|
131
|
-
apiGlobals?: object;
|
|
132
|
-
apiDefFilePath: string; // Full path to the api definition file so that it can be loaded into the prompt
|
|
133
|
-
apiGlobalName?: string;
|
|
134
|
-
apiDocsPath?: string;
|
|
135
|
-
debug?: boolean;
|
|
136
|
-
model?: string;
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
137
215
|
};
|
|
138
216
|
|
|
139
|
-
export interface AIMyAPIInstance {
|
|
140
|
-
// see xample 2
|
|
141
|
-
options:AIMyAPIOptions;
|
|
142
|
-
generateCode: (queryText:string, userChatHistory:ChatCompletionMessageParam[]) => Promise<GenerateCodeResult>;
|
|
143
|
-
runCode: (task:string) => Promise<void>;
|
|
144
|
-
// run a single request with no history
|
|
145
|
-
processRequest: (userQuery:string, context?: object) => Promise<GenerateCodeResult>;
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
217
|
async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
150
218
|
// extend options with defaults
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
219
|
+
const localOptions = {
|
|
220
|
+
...{
|
|
221
|
+
apiGlobalName: "api",
|
|
222
|
+
apiGlobals: {},
|
|
223
|
+
apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
|
|
224
|
+
debug: false,
|
|
225
|
+
model: process.env.OPENAI_API_MODEL ||"gpt-5.4-mini",
|
|
226
|
+
additionalModelOptions: {},
|
|
227
|
+
hideLogsFromAgent: false,
|
|
228
|
+
},
|
|
157
229
|
...options
|
|
158
|
-
}
|
|
230
|
+
};
|
|
159
231
|
|
|
160
|
-
if(!
|
|
161
|
-
throw new Error("apiObject and
|
|
232
|
+
if(!localOptions.apiObject || !localOptions.apiDefFilePath) {
|
|
233
|
+
throw new Error("apiObject and apiDefFilePath are required");
|
|
162
234
|
}
|
|
163
235
|
|
|
164
|
-
const {apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model} =
|
|
236
|
+
const {apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model, additionalModelOptions, hideLogsFromAgent} = localOptions;
|
|
165
237
|
|
|
166
|
-
const createTaskPrompt = createBasePrompt( apiDefFilePath, apiDocsPath);
|
|
238
|
+
const createTaskPrompt = createBasePrompt( apiDefFilePath, apiGlobalName, apiDocsPath);
|
|
167
239
|
|
|
168
|
-
|
|
169
|
-
options,
|
|
170
|
-
generateCode: async function(queryText:string, userChatHistory:ChatCompletionMessageParam[], currentContext:any = undefined) {
|
|
240
|
+
const instance = {
|
|
241
|
+
options: localOptions,
|
|
242
|
+
generateCode: async function(queryText:string, userChatHistory:ChatCompletionMessageParam[], currentContext:any = undefined) {
|
|
171
243
|
if(!queryText)
|
|
172
|
-
return
|
|
173
|
-
|
|
174
|
-
|
|
244
|
+
return null;
|
|
245
|
+
|
|
246
|
+
const formattedContext = wrapCodeBlock(JSON.stringify(currentContext, null, 2), "json");
|
|
247
|
+
|
|
248
|
+
return await generateCode(instance,
|
|
249
|
+
queryText,
|
|
250
|
+
userChatHistory,
|
|
251
|
+
createTaskPrompt.replace("{{CONTEXT}}", formattedContext),
|
|
252
|
+
debug,
|
|
253
|
+
hideLogsFromAgent,
|
|
254
|
+
model,
|
|
255
|
+
additionalModelOptions
|
|
256
|
+
);
|
|
175
257
|
},
|
|
176
|
-
|
|
258
|
+
checkCode: async function (generatedCode:string): Promise<CodeRunResult> {
|
|
177
259
|
if(!QuickJS) {
|
|
178
260
|
// Create QuickJS
|
|
179
261
|
if(debug)
|
|
@@ -181,18 +263,93 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
181
263
|
QuickJS = await getQuickJS();
|
|
182
264
|
}
|
|
183
265
|
|
|
184
|
-
let apiGlobals = {}
|
|
266
|
+
let apiGlobals: { [key: string]: { value: any } } = {}
|
|
185
267
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
268
|
+
if(options.apiGlobals) {
|
|
269
|
+
for(const key in options.apiGlobals) {
|
|
270
|
+
apiGlobals[key] = {
|
|
271
|
+
value: (options.apiGlobals as Record<string, any>)[key],
|
|
272
|
+
}
|
|
189
273
|
}
|
|
190
274
|
}
|
|
191
|
-
|
|
275
|
+
|
|
276
|
+
// Create sandbox
|
|
277
|
+
const {vm, checkCode} = await createSandbox(QuickJS, {
|
|
278
|
+
[apiDefFilePath]: apiExports,
|
|
279
|
+
}, {
|
|
280
|
+
...apiGlobals,
|
|
281
|
+
[apiGlobalName]: {
|
|
282
|
+
value: apiObject,
|
|
283
|
+
whitelist: apiWhitelist
|
|
284
|
+
}
|
|
285
|
+
}, options.debug);
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
if(debug) {
|
|
289
|
+
console.log("checking Code:\n", generatedCode);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const res = await checkCode(wrapCode(apiGlobalName, apiDefFilePath, generatedCode));
|
|
293
|
+
|
|
294
|
+
if(!res) {
|
|
295
|
+
console.error("Unknown failure checking code");
|
|
296
|
+
return {
|
|
297
|
+
success: false,
|
|
298
|
+
logs: [],
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
if(debug) {
|
|
304
|
+
console.log(res.success ? "Code check passed" : "Code check failed");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if(res.success) {
|
|
308
|
+
return {
|
|
309
|
+
success: true,
|
|
310
|
+
logs: [{ type: "log", args: ["✔️ Code check passed"], source: "compiler" }, ...res.logs],
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
success: false,
|
|
316
|
+
logs: [{ type: "error", args: ["❌ Code check failed"], source: "compiler" }, ...res.logs],
|
|
317
|
+
};
|
|
318
|
+
} catch(err) {
|
|
319
|
+
if(debug) {
|
|
320
|
+
console.error("Error checking code:", err);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
vm.dispose();
|
|
324
|
+
|
|
325
|
+
return {
|
|
326
|
+
success: false,
|
|
327
|
+
logs: [],
|
|
328
|
+
};
|
|
329
|
+
},
|
|
330
|
+
runCode: async function (code:string): Promise<CodeRunResult> {
|
|
331
|
+
// TODO: fix code duplication with checkCode, maybe combine into a single function that takes a parameter for whether to actually run the code or just check it?
|
|
332
|
+
if(!QuickJS) {
|
|
333
|
+
// Create QuickJS
|
|
334
|
+
if(debug)
|
|
335
|
+
console.log("Creating quick.js");
|
|
336
|
+
QuickJS = await getQuickJS();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
let apiGlobals: { [key: string]: { value: any } } = {}
|
|
340
|
+
|
|
341
|
+
if(options.apiGlobals) {
|
|
342
|
+
for(const key in options.apiGlobals) {
|
|
343
|
+
apiGlobals[key] = {
|
|
344
|
+
value: (options.apiGlobals as Record<string, any>)[key],
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
192
349
|
// Create sandbox
|
|
193
350
|
// NOTE: not sure why I have to replace the backslash here
|
|
194
|
-
const {vm, runTask, isAsyncProcessRunning} = await createSandbox(QuickJS, {
|
|
195
|
-
[apiDefFilePath
|
|
351
|
+
const {vm, runCode: runTask, isAsyncProcessRunning} = await createSandbox(QuickJS, {
|
|
352
|
+
[apiDefFilePath]: apiExports,
|
|
196
353
|
}, {
|
|
197
354
|
...apiGlobals,
|
|
198
355
|
[apiGlobalName]: {
|
|
@@ -203,13 +360,17 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
203
360
|
|
|
204
361
|
try {
|
|
205
362
|
if(debug) {
|
|
206
|
-
console.log("Running Code:\n",
|
|
363
|
+
console.log("Running Code:\n", code);
|
|
207
364
|
}
|
|
208
365
|
|
|
209
|
-
const res = await runTask(
|
|
366
|
+
const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
|
|
210
367
|
|
|
211
368
|
if(!res) {
|
|
212
|
-
console.error("
|
|
369
|
+
console.error("Unknown failure running task");
|
|
370
|
+
return {
|
|
371
|
+
success: false,
|
|
372
|
+
logs: [],
|
|
373
|
+
};
|
|
213
374
|
}
|
|
214
375
|
|
|
215
376
|
while(isAsyncProcessRunning()) {
|
|
@@ -219,6 +380,8 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
219
380
|
if(debug) {
|
|
220
381
|
console.log("Completed");
|
|
221
382
|
}
|
|
383
|
+
|
|
384
|
+
return res;
|
|
222
385
|
} catch(err) {
|
|
223
386
|
if(debug) {
|
|
224
387
|
console.error("Error running task:", err);
|
|
@@ -228,10 +391,15 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
228
391
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
229
392
|
|
|
230
393
|
rejectOpenPromises(vm);
|
|
231
|
-
vm.dispose()
|
|
232
|
-
|
|
394
|
+
vm.dispose();
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
logs: [],
|
|
399
|
+
};
|
|
233
400
|
},
|
|
234
|
-
|
|
401
|
+
// generates code and runs it in one step
|
|
402
|
+
processRequest: async function (userQuery: string, currentContext:any = undefined):Promise<GenerateCodeResult | null> {
|
|
235
403
|
// Create prompt
|
|
236
404
|
|
|
237
405
|
if(debug) {
|
|
@@ -240,24 +408,38 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
240
408
|
|
|
241
409
|
// Generate Code
|
|
242
410
|
console.time("Generate Task")
|
|
243
|
-
const generatedCode:GenerateCodeResult = await generateCode(
|
|
411
|
+
const generatedCode:GenerateCodeResult | null = await generateCode(instance,
|
|
412
|
+
userQuery,
|
|
413
|
+
[],
|
|
414
|
+
createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : "" ),
|
|
415
|
+
debug,
|
|
416
|
+
hideLogsFromAgent,
|
|
417
|
+
model,
|
|
418
|
+
additionalModelOptions
|
|
419
|
+
);
|
|
244
420
|
console.timeEnd("Generate Task")
|
|
245
421
|
|
|
246
422
|
console.time("Run Code")
|
|
247
|
-
|
|
423
|
+
if(generatedCode?.code) {
|
|
424
|
+
await instance.runCode(generatedCode.code);
|
|
425
|
+
} else {
|
|
426
|
+
console.error("No code generated", generatedCode);
|
|
427
|
+
}
|
|
248
428
|
console.timeEnd("Run Code")
|
|
249
429
|
|
|
250
430
|
return generatedCode;
|
|
251
431
|
}
|
|
252
432
|
}
|
|
253
433
|
|
|
434
|
+
return instance;
|
|
435
|
+
|
|
254
436
|
}
|
|
255
437
|
|
|
256
438
|
export interface AIMyAPIModuleExports {
|
|
257
439
|
createWithAPI: (options:AIMyAPIOptions) => Promise<AIMyAPIInstance>;
|
|
258
440
|
|
|
259
441
|
createBasePrompt: (apiFilePath:string, documentationPath: string) => string;
|
|
260
|
-
generateCode: (queryText:string, userChatHistory:ChatCompletionMessageParam[], createTaskPrompt:string, debug:boolean) => Promise<GenerateCodeResult>;
|
|
442
|
+
generateCode: (instance: AIMyAPIInstance, queryText:string, userChatHistory:ChatCompletionMessageParam[], createTaskPrompt:string, debug:boolean) => Promise<GenerateCodeResult | null>;
|
|
261
443
|
createSandbox: (QuickJS:QuickJSWASMModule, globals: any) => Promise<any>;
|
|
262
444
|
}
|
|
263
445
|
|
|
@@ -270,3 +452,6 @@ export const AIMyAPI:AIMyAPIModuleExports = {
|
|
|
270
452
|
generateCode,
|
|
271
453
|
createSandbox,
|
|
272
454
|
}
|
|
455
|
+
|
|
456
|
+
export * from "./sandbox";
|
|
457
|
+
|