aimyapi 0.2.0 → 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 +336 -101
- 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 +336 -101
- package/dist/index.mjs +336 -102
- package/example/example1.ts +11 -8
- package/example/example2.ts +31 -20
- package/example/example3.ts +25 -18
- package/example/ordering_api.md +54 -109
- package/example/ordering_api.ts +3 -2
- package/example/ordering_api_impl.ts +2 -1
- package/example/sales_api.md +3 -16
- 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 +329 -126
- package/src/sandbox.ts +119 -26
- package/tsconfig.json +1 -0
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,8 @@ import { OpenAI } from 'openai';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { getQuickJS } from 'quickjs-emscripten';
|
|
6
6
|
import * as ts from 'typescript';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
7
9
|
|
|
8
10
|
var require$1 = (
|
|
9
11
|
true
|
|
@@ -196,8 +198,8 @@ function injectTimingFunctions(vm, cbAddedTimer, cbRemovedTimer, maxTimeout = 6e
|
|
|
196
198
|
_clearInterval.dispose();
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
function tsCompile(source, options
|
|
200
|
-
if (
|
|
201
|
+
function tsCompile(source, options) {
|
|
202
|
+
if (!options) {
|
|
201
203
|
options = {
|
|
202
204
|
compilerOptions: {
|
|
203
205
|
target: ts.ScriptTarget.ES2020,
|
|
@@ -207,6 +209,34 @@ function tsCompile(source, options = null) {
|
|
|
207
209
|
}
|
|
208
210
|
return ts.transpileModule(source, options).outputText;
|
|
209
211
|
}
|
|
212
|
+
class Logger {
|
|
213
|
+
constructor(debug = false) {
|
|
214
|
+
this.logs = [];
|
|
215
|
+
this.debug = false;
|
|
216
|
+
this.debug = debug;
|
|
217
|
+
}
|
|
218
|
+
log(args, source) {
|
|
219
|
+
if (Array.isArray(args)) {
|
|
220
|
+
this.logs.push({ type: "log", args, source });
|
|
221
|
+
} else {
|
|
222
|
+
this.logs.push({ type: "log", args: [args], source });
|
|
223
|
+
}
|
|
224
|
+
if (this.debug) {
|
|
225
|
+
console.log(`[${source}]:`, ...args);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
error(args, source) {
|
|
229
|
+
if (Array.isArray(args)) {
|
|
230
|
+
this.logs.push({ type: "error", args, source });
|
|
231
|
+
} else {
|
|
232
|
+
this.logs.push({ type: "error", args: [args], source });
|
|
233
|
+
}
|
|
234
|
+
console.error(`[${source}]:`, ...args);
|
|
235
|
+
}
|
|
236
|
+
clear() {
|
|
237
|
+
this.logs = [];
|
|
238
|
+
}
|
|
239
|
+
}
|
|
210
240
|
async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug = false) {
|
|
211
241
|
const vm = QuickJS.newContext();
|
|
212
242
|
let errorState = false;
|
|
@@ -223,20 +253,21 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
223
253
|
let isAsyncProcessRunning = () => {
|
|
224
254
|
return asyncProcessesRunning > 0;
|
|
225
255
|
};
|
|
256
|
+
const logger = new Logger(debug);
|
|
226
257
|
const logHandle = vm.newFunction("log", (...args) => {
|
|
227
258
|
const nativeArgs = args.map(vm.dump);
|
|
228
|
-
|
|
259
|
+
logger.log(nativeArgs, "sandbox");
|
|
229
260
|
});
|
|
230
261
|
const consoleHandle = vm.newObject();
|
|
231
262
|
const exportsHandle = vm.newObject();
|
|
232
263
|
const errorHandle = vm.newFunction("error", (...args) => {
|
|
233
264
|
try {
|
|
234
265
|
const nativeArgs = args.map(vm.dump);
|
|
235
|
-
|
|
266
|
+
logger.error(nativeArgs, "sandbox");
|
|
236
267
|
lastError = JSON.stringify(nativeArgs);
|
|
237
268
|
errorState = true;
|
|
238
269
|
} catch (e) {
|
|
239
|
-
|
|
270
|
+
logger.error(["? Error in error:", e], "sandbox");
|
|
240
271
|
}
|
|
241
272
|
});
|
|
242
273
|
const globalNames = Object.getOwnPropertyNames(globals);
|
|
@@ -278,147 +309,326 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
278
309
|
return lastError;
|
|
279
310
|
},
|
|
280
311
|
isAsyncProcessRunning,
|
|
281
|
-
|
|
312
|
+
// make sure code passes the typescript compilation
|
|
313
|
+
checkCode: (code) => {
|
|
314
|
+
logger.clear();
|
|
282
315
|
try {
|
|
283
|
-
const compiled = tsCompile(
|
|
316
|
+
const compiled = tsCompile(code);
|
|
284
317
|
if (!compiled || compiled.length === 0) {
|
|
285
|
-
|
|
286
|
-
return
|
|
318
|
+
logger.error(["Could not compile:", code], "compiler");
|
|
319
|
+
return {
|
|
320
|
+
success: false,
|
|
321
|
+
logs: logger.logs
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
} catch (e) {
|
|
325
|
+
logger.error(["Error testing code:", e], "compiler");
|
|
326
|
+
return {
|
|
327
|
+
success: false,
|
|
328
|
+
logs: logger.logs
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
success: true,
|
|
333
|
+
logs: logger.logs
|
|
334
|
+
};
|
|
335
|
+
},
|
|
336
|
+
runCode: (code) => {
|
|
337
|
+
try {
|
|
338
|
+
logger.clear();
|
|
339
|
+
const compiled = tsCompile(code);
|
|
340
|
+
if (!compiled || compiled.length === 0) {
|
|
341
|
+
logger.error(["Could not compile:", code], "compiler");
|
|
342
|
+
return {
|
|
343
|
+
success: false,
|
|
344
|
+
logs: logger.logs
|
|
345
|
+
};
|
|
287
346
|
}
|
|
288
347
|
errorState = false;
|
|
289
348
|
const result = vm.evalCode(compiled);
|
|
290
349
|
if (result.error) {
|
|
291
|
-
const lines = compiled.split("\n");
|
|
292
|
-
|
|
293
|
-
console.log(`${i + 1}: ${lines[i]}`);
|
|
294
|
-
}
|
|
295
|
-
console.log("Execution failed:", vm.dump(result.error));
|
|
350
|
+
const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
|
|
351
|
+
logger.error(["Execution failed:", lines.join("\n"), vm.dump(result.error)], "runner");
|
|
296
352
|
result.error.dispose();
|
|
297
|
-
return
|
|
298
|
-
|
|
353
|
+
return {
|
|
354
|
+
success: false,
|
|
355
|
+
logs: logger.logs
|
|
356
|
+
};
|
|
357
|
+
} else if ("value" in result) {
|
|
299
358
|
result.value.dispose();
|
|
300
359
|
if (errorState) {
|
|
301
|
-
const lines = compiled.split("\n");
|
|
302
|
-
|
|
303
|
-
console.log(`${i + 1}: ${lines[i]}`);
|
|
304
|
-
}
|
|
360
|
+
const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
|
|
361
|
+
logger.error(["An error was reported during execution. Compiled code with line numbers:", lines.join("\n")], "runner");
|
|
305
362
|
}
|
|
306
|
-
return
|
|
363
|
+
return {
|
|
364
|
+
success: !errorState,
|
|
365
|
+
logs: logger.logs
|
|
366
|
+
};
|
|
367
|
+
} else {
|
|
368
|
+
logger.error(["Unknown execution result:", result], "runner");
|
|
369
|
+
return {
|
|
370
|
+
success: false,
|
|
371
|
+
logs: logger.logs
|
|
372
|
+
};
|
|
307
373
|
}
|
|
308
374
|
} catch (e) {
|
|
309
|
-
|
|
375
|
+
logger.error(["Error running code:", e], "runner");
|
|
310
376
|
}
|
|
311
|
-
return
|
|
377
|
+
return {
|
|
378
|
+
success: false,
|
|
379
|
+
logs: logger.logs
|
|
380
|
+
};
|
|
312
381
|
}
|
|
313
382
|
};
|
|
314
383
|
}
|
|
315
384
|
|
|
316
385
|
require$1("dotenv").config();
|
|
317
|
-
const openai = new OpenAI(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
386
|
+
const openai = new OpenAI();
|
|
387
|
+
let QuickJS = null;
|
|
388
|
+
const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
|
|
389
|
+
(async () => {
|
|
390
|
+
try {
|
|
391
|
+
${code}
|
|
392
|
+
} catch(err) {
|
|
393
|
+
console.error(err);
|
|
394
|
+
}
|
|
395
|
+
})();
|
|
396
|
+
`;
|
|
397
|
+
const wrapCodeBlock = (code, codeType = "") => `
|
|
398
|
+
\`\`\`${codeType}
|
|
399
|
+
${code}
|
|
400
|
+
\`\`\`
|
|
401
|
+
`;
|
|
402
|
+
function zodParseJSON(schema) {
|
|
403
|
+
return (input) => schema.parse(JSON.parse(input));
|
|
404
|
+
}
|
|
405
|
+
function createBasePrompt(apiFilePath, apiGlobalName, documentationPath) {
|
|
322
406
|
const apiText = fs.readFileSync(apiFilePath, "utf8");
|
|
323
407
|
const documentationText = documentationPath ? fs.readFileSync(documentationPath, "utf8") : "";
|
|
324
|
-
const createTaskPrompt = fs.readFileSync(path.join(__dirname, "../prompts/create-task-prompt.md"), "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText);
|
|
408
|
+
const createTaskPrompt = fs.readFileSync(path.join(__dirname, "../prompts/create-task-prompt.md"), "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
|
|
325
409
|
return createTaskPrompt;
|
|
326
410
|
}
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
411
|
+
const runCodeSchema = z.object({
|
|
412
|
+
code: z.string()
|
|
413
|
+
});
|
|
414
|
+
const checkCodeSchema = z.object({
|
|
415
|
+
code: z.string()
|
|
416
|
+
});
|
|
417
|
+
const submitCodeSchema = z.object({
|
|
418
|
+
code: z.string()
|
|
419
|
+
});
|
|
420
|
+
const generateCode = async function(instance, queryText, userChatHistory, createTaskPrompt, debug = false, hideLogsFromAgent = false, model = "gpt-5-mini", additionalModelOptions) {
|
|
421
|
+
let finalSubmittedCode = "";
|
|
422
|
+
if (debug) {
|
|
423
|
+
console.log("Generating code for query:", queryText);
|
|
424
|
+
}
|
|
425
|
+
const codingTools = [
|
|
426
|
+
{
|
|
427
|
+
type: "function",
|
|
428
|
+
function: {
|
|
429
|
+
name: "runCode",
|
|
430
|
+
// @ts-ignore
|
|
431
|
+
function: async ({ code }) => {
|
|
432
|
+
if (debug) {
|
|
433
|
+
console.log("Running code...", code);
|
|
434
|
+
}
|
|
435
|
+
const res = await instance.runCode(code);
|
|
436
|
+
if (hideLogsFromAgent) {
|
|
437
|
+
res.logs = [];
|
|
438
|
+
}
|
|
439
|
+
return res;
|
|
440
|
+
},
|
|
441
|
+
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.",
|
|
442
|
+
parse: zodParseJSON(runCodeSchema),
|
|
443
|
+
parameters: zodToJsonSchema(runCodeSchema)
|
|
444
|
+
}
|
|
445
|
+
},
|
|
332
446
|
{
|
|
333
|
-
|
|
334
|
-
|
|
447
|
+
type: "function",
|
|
448
|
+
function: {
|
|
449
|
+
name: "checkCode",
|
|
450
|
+
// @ts-ignore
|
|
451
|
+
function: async ({ code }) => {
|
|
452
|
+
if (debug) {
|
|
453
|
+
console.log("Checking code...", code);
|
|
454
|
+
}
|
|
455
|
+
const res = await instance.checkCode(code);
|
|
456
|
+
return res;
|
|
457
|
+
},
|
|
458
|
+
description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
|
|
459
|
+
parse: zodParseJSON(checkCodeSchema),
|
|
460
|
+
parameters: zodToJsonSchema(checkCodeSchema)
|
|
461
|
+
}
|
|
335
462
|
},
|
|
336
|
-
...userChatHistory,
|
|
337
463
|
{
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
464
|
+
type: "function",
|
|
465
|
+
function: {
|
|
466
|
+
name: "submitCode",
|
|
467
|
+
// @ts-ignore
|
|
468
|
+
function: async ({ code }) => {
|
|
469
|
+
finalSubmittedCode = code;
|
|
470
|
+
return {
|
|
471
|
+
success: true
|
|
472
|
+
};
|
|
473
|
+
},
|
|
474
|
+
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.",
|
|
475
|
+
parse: zodParseJSON(submitCodeSchema),
|
|
476
|
+
parameters: zodToJsonSchema(submitCodeSchema)
|
|
477
|
+
}
|
|
341
478
|
}
|
|
342
479
|
];
|
|
343
480
|
try {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
type: "object",
|
|
356
|
-
properties: {
|
|
357
|
-
yourCode: {
|
|
358
|
-
type: "string",
|
|
359
|
-
description: "The code generated by the AI"
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
type: "json_schema"
|
|
481
|
+
const runner = openai.chat.completions.runTools({
|
|
482
|
+
model,
|
|
483
|
+
messages: [
|
|
484
|
+
{
|
|
485
|
+
role: "system",
|
|
486
|
+
content: "You will assist with writing code to perform the user's request."
|
|
487
|
+
},
|
|
488
|
+
...userChatHistory,
|
|
489
|
+
{
|
|
490
|
+
role: "user",
|
|
491
|
+
content: createTaskPrompt.replace("{{USER_QUERY}}", queryText)
|
|
365
492
|
}
|
|
493
|
+
],
|
|
494
|
+
tools: codingTools,
|
|
495
|
+
...additionalModelOptions
|
|
496
|
+
}).on("message", async (message) => {
|
|
497
|
+
if (debug) {
|
|
498
|
+
console.log("Message:", JSON.stringify(message, null, 2));
|
|
366
499
|
}
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
console.
|
|
379
|
-
return { code: "", loggableCode: "" };
|
|
500
|
+
}).on("functionToolCall", (functionCall) => {
|
|
501
|
+
if (debug) {
|
|
502
|
+
console.log("Function Call:", JSON.stringify(functionCall, null, 2));
|
|
503
|
+
}
|
|
504
|
+
}).on("functionToolCallResult", (functionCall) => {
|
|
505
|
+
if (debug) {
|
|
506
|
+
console.log("Function Call Result:", JSON.stringify(functionCall, null, 2));
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
const finalContent = await runner.finalContent();
|
|
510
|
+
if (debug) {
|
|
511
|
+
console.log("Final Content:", finalContent);
|
|
380
512
|
}
|
|
513
|
+
return {
|
|
514
|
+
code: finalSubmittedCode,
|
|
515
|
+
comments: finalContent || void 0
|
|
516
|
+
};
|
|
381
517
|
} catch (err) {
|
|
382
518
|
console.error(err);
|
|
383
|
-
return
|
|
519
|
+
return null;
|
|
384
520
|
}
|
|
385
521
|
};
|
|
386
|
-
let QuickJS = null;
|
|
387
522
|
async function createWithAPI(options) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
523
|
+
const localOptions = {
|
|
524
|
+
...{
|
|
525
|
+
apiGlobalName: "api",
|
|
526
|
+
apiGlobals: {},
|
|
527
|
+
apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
|
|
528
|
+
debug: false,
|
|
529
|
+
model: process.env.OPENAI_API_MODEL || "gpt-5.4-mini",
|
|
530
|
+
additionalModelOptions: {},
|
|
531
|
+
hideLogsFromAgent: false
|
|
532
|
+
},
|
|
394
533
|
...options
|
|
395
534
|
};
|
|
396
|
-
if (!
|
|
397
|
-
throw new Error("apiObject and
|
|
535
|
+
if (!localOptions.apiObject || !localOptions.apiDefFilePath) {
|
|
536
|
+
throw new Error("apiObject and apiDefFilePath are required");
|
|
398
537
|
}
|
|
399
|
-
const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model } =
|
|
400
|
-
const createTaskPrompt = createBasePrompt(apiDefFilePath, apiDocsPath);
|
|
401
|
-
|
|
402
|
-
options,
|
|
538
|
+
const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model, additionalModelOptions, hideLogsFromAgent } = localOptions;
|
|
539
|
+
const createTaskPrompt = createBasePrompt(apiDefFilePath, apiGlobalName, apiDocsPath);
|
|
540
|
+
const instance = {
|
|
541
|
+
options: localOptions,
|
|
403
542
|
generateCode: async function(queryText, userChatHistory, currentContext = void 0) {
|
|
404
543
|
if (!queryText)
|
|
405
|
-
return
|
|
406
|
-
|
|
544
|
+
return null;
|
|
545
|
+
const formattedContext = wrapCodeBlock(JSON.stringify(currentContext, null, 2), "json");
|
|
546
|
+
return await generateCode(
|
|
547
|
+
instance,
|
|
548
|
+
queryText,
|
|
549
|
+
userChatHistory,
|
|
550
|
+
createTaskPrompt.replace("{{CONTEXT}}", formattedContext),
|
|
551
|
+
debug,
|
|
552
|
+
hideLogsFromAgent,
|
|
553
|
+
model,
|
|
554
|
+
additionalModelOptions
|
|
555
|
+
);
|
|
407
556
|
},
|
|
408
|
-
|
|
557
|
+
checkCode: async function(generatedCode) {
|
|
409
558
|
if (!QuickJS) {
|
|
410
559
|
if (debug)
|
|
411
560
|
console.log("Creating quick.js");
|
|
412
561
|
QuickJS = await getQuickJS();
|
|
413
562
|
}
|
|
414
563
|
let apiGlobals = {};
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
564
|
+
if (options.apiGlobals) {
|
|
565
|
+
for (const key in options.apiGlobals) {
|
|
566
|
+
apiGlobals[key] = {
|
|
567
|
+
value: options.apiGlobals[key]
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
const { vm, checkCode } = await createSandbox(QuickJS, {
|
|
572
|
+
[apiDefFilePath]: apiExports
|
|
573
|
+
}, {
|
|
574
|
+
...apiGlobals,
|
|
575
|
+
[apiGlobalName]: {
|
|
576
|
+
value: apiObject,
|
|
577
|
+
whitelist: apiWhitelist
|
|
578
|
+
}
|
|
579
|
+
}, options.debug);
|
|
580
|
+
try {
|
|
581
|
+
if (debug) {
|
|
582
|
+
console.log("checking Code:\n", generatedCode);
|
|
583
|
+
}
|
|
584
|
+
const res = await checkCode(wrapCode(apiGlobalName, apiDefFilePath, generatedCode));
|
|
585
|
+
if (!res) {
|
|
586
|
+
console.error("Unknown failure checking code");
|
|
587
|
+
return {
|
|
588
|
+
success: false,
|
|
589
|
+
logs: []
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (debug) {
|
|
593
|
+
console.log(res.success ? "Code check passed" : "Code check failed");
|
|
594
|
+
}
|
|
595
|
+
if (res.success) {
|
|
596
|
+
return {
|
|
597
|
+
success: true,
|
|
598
|
+
logs: [{ type: "log", args: ["\u2714\uFE0F Code check passed"], source: "compiler" }, ...res.logs]
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
success: false,
|
|
603
|
+
logs: [{ type: "error", args: ["\u274C Code check failed"], source: "compiler" }, ...res.logs]
|
|
418
604
|
};
|
|
605
|
+
} catch (err) {
|
|
606
|
+
if (debug) {
|
|
607
|
+
console.error("Error checking code:", err);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
vm.dispose();
|
|
611
|
+
return {
|
|
612
|
+
success: false,
|
|
613
|
+
logs: []
|
|
614
|
+
};
|
|
615
|
+
},
|
|
616
|
+
runCode: async function(code) {
|
|
617
|
+
if (!QuickJS) {
|
|
618
|
+
if (debug)
|
|
619
|
+
console.log("Creating quick.js");
|
|
620
|
+
QuickJS = await getQuickJS();
|
|
419
621
|
}
|
|
420
|
-
|
|
421
|
-
|
|
622
|
+
let apiGlobals = {};
|
|
623
|
+
if (options.apiGlobals) {
|
|
624
|
+
for (const key in options.apiGlobals) {
|
|
625
|
+
apiGlobals[key] = {
|
|
626
|
+
value: options.apiGlobals[key]
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, {
|
|
631
|
+
[apiDefFilePath]: apiExports
|
|
422
632
|
}, {
|
|
423
633
|
...apiGlobals,
|
|
424
634
|
[apiGlobalName]: {
|
|
@@ -428,11 +638,15 @@ async function createWithAPI(options) {
|
|
|
428
638
|
}, options.debug);
|
|
429
639
|
try {
|
|
430
640
|
if (debug) {
|
|
431
|
-
console.log("Running Code:\n",
|
|
641
|
+
console.log("Running Code:\n", code);
|
|
432
642
|
}
|
|
433
|
-
const res = await runTask(
|
|
643
|
+
const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
|
|
434
644
|
if (!res) {
|
|
435
|
-
console.error("
|
|
645
|
+
console.error("Unknown failure running task");
|
|
646
|
+
return {
|
|
647
|
+
success: false,
|
|
648
|
+
logs: []
|
|
649
|
+
};
|
|
436
650
|
}
|
|
437
651
|
while (isAsyncProcessRunning()) {
|
|
438
652
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -440,6 +654,7 @@ async function createWithAPI(options) {
|
|
|
440
654
|
if (debug) {
|
|
441
655
|
console.log("Completed");
|
|
442
656
|
}
|
|
657
|
+
return res;
|
|
443
658
|
} catch (err) {
|
|
444
659
|
if (debug) {
|
|
445
660
|
console.error("Error running task:", err);
|
|
@@ -448,20 +663,39 @@ async function createWithAPI(options) {
|
|
|
448
663
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
449
664
|
rejectOpenPromises(vm);
|
|
450
665
|
vm.dispose();
|
|
666
|
+
return {
|
|
667
|
+
success: false,
|
|
668
|
+
logs: []
|
|
669
|
+
};
|
|
451
670
|
},
|
|
671
|
+
// generates code and runs it in one step
|
|
452
672
|
processRequest: async function(userQuery, currentContext = void 0) {
|
|
453
673
|
if (debug) {
|
|
454
674
|
console.log("Query:", userQuery);
|
|
455
675
|
}
|
|
456
676
|
console.time("Generate Task");
|
|
457
|
-
const generatedCode = await generateCode(
|
|
677
|
+
const generatedCode = await generateCode(
|
|
678
|
+
instance,
|
|
679
|
+
userQuery,
|
|
680
|
+
[],
|
|
681
|
+
createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : ""),
|
|
682
|
+
debug,
|
|
683
|
+
hideLogsFromAgent,
|
|
684
|
+
model,
|
|
685
|
+
additionalModelOptions
|
|
686
|
+
);
|
|
458
687
|
console.timeEnd("Generate Task");
|
|
459
688
|
console.time("Run Code");
|
|
460
|
-
|
|
689
|
+
if (generatedCode?.code) {
|
|
690
|
+
await instance.runCode(generatedCode.code);
|
|
691
|
+
} else {
|
|
692
|
+
console.error("No code generated", generatedCode);
|
|
693
|
+
}
|
|
461
694
|
console.timeEnd("Run Code");
|
|
462
695
|
return generatedCode;
|
|
463
696
|
}
|
|
464
697
|
};
|
|
698
|
+
return instance;
|
|
465
699
|
}
|
|
466
700
|
const AIMyAPI = {
|
|
467
701
|
// Standard way of using the library
|
|
@@ -472,4 +706,4 @@ const AIMyAPI = {
|
|
|
472
706
|
createSandbox
|
|
473
707
|
};
|
|
474
708
|
|
|
475
|
-
export { AIMyAPI, createBasePrompt, generateCode };
|
|
709
|
+
export { AIMyAPI, createBasePrompt, generateCode, zodParseJSON };
|
package/example/example1.ts
CHANGED
|
@@ -10,21 +10,24 @@ import { API } from "./sales_api_impl";
|
|
|
10
10
|
|
|
11
11
|
const aimyapi = await AIMyAPI.createWithAPI({
|
|
12
12
|
apiObject: api,
|
|
13
|
-
apiGlobalName: "
|
|
13
|
+
apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
|
|
14
14
|
apiExports: APIExports,
|
|
15
15
|
apiDefFilePath: path.join(__dirname, "./sales_api.ts"),
|
|
16
16
|
apiDocsPath: path.join(__dirname, "./sales_api.md"),
|
|
17
|
-
debug:
|
|
17
|
+
debug: false,
|
|
18
18
|
})
|
|
19
|
+
|
|
20
|
+
aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
console.log("Print 'hello' three times.")
|
|
23
|
+
await aimyapi.processRequest("Print 'hello' three times.");
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
console.log("What month had the highest sales in 2020 for any business unit?")
|
|
26
|
+
await aimyapi.processRequest("What was our best month in 2020");
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
console.log("Which business unit had the highest sales in 2020? Print the totals for each")
|
|
29
|
+
await aimyapi.processRequest("Which business unit had the highest sales in 2020? Print the totals for each");
|
|
30
|
+
// Note: this is a bit of a trick question because two of them are tied for first. The agent usually doesn't realize this edge case. Should we instruct it to look for edge cases?
|
|
28
31
|
|
|
29
32
|
console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
|
|
30
33
|
await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
|
package/example/example2.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
// Note: This example is quite stupid and slow and you'd be better off using Tool calling for something like this, but I'm leaving it for demonstration purposes
|
|
2
|
+
|
|
1
3
|
import path from "path";
|
|
2
|
-
import { AIMyAPI
|
|
4
|
+
import { AIMyAPI } from "../src";
|
|
3
5
|
import * as APIExports from "./ordering_api";
|
|
4
6
|
import { OrderingAPI } from "./ordering_api_impl";
|
|
5
7
|
|
|
6
8
|
// More complex fast food ordering example that uses chat history.
|
|
7
9
|
// Fast food ordering example.
|
|
8
10
|
|
|
9
|
-
// IDEA: If the order history becomes too long, we could summarize it by listing the current order state and remove the rest.
|
|
10
11
|
(async () => {
|
|
11
|
-
const
|
|
12
|
+
const orderingApi = new OrderingAPI();
|
|
12
13
|
|
|
13
14
|
const options = {
|
|
14
|
-
apiObject:
|
|
15
|
+
apiObject: orderingApi,
|
|
15
16
|
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
17
|
+
apiGlobals: {
|
|
18
|
+
Menu: APIExports.Menu,
|
|
19
|
+
},
|
|
16
20
|
apiExports: APIExports,
|
|
17
21
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
18
22
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
@@ -24,22 +28,29 @@ import { OrderingAPI } from "./ordering_api_impl";
|
|
|
24
28
|
console.log(`Query: ${query}`)
|
|
25
29
|
|
|
26
30
|
// generate the code for this query
|
|
27
|
-
const codeResult
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
const codeResult = await aimyapi.generateCode(query, orderingApi._getHistory());
|
|
32
|
+
|
|
33
|
+
if(codeResult) {
|
|
34
|
+
orderingApi._addMessageToHistory({
|
|
35
|
+
content: query,
|
|
36
|
+
role: "user",
|
|
37
|
+
name: "user",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
orderingApi._addMessageToHistory({
|
|
41
|
+
content: codeResult.comments || "done",
|
|
42
|
+
role: "assistant",
|
|
43
|
+
name: "assistant",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// run the code in the sandbox
|
|
47
|
+
if(codeResult.code) {
|
|
48
|
+
await aimyapi.runCode(codeResult.code);
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
console.error("No code generated for this query.");
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
}
|
|
44
55
|
|
|
45
56
|
await runQuery("How's the burger here?");
|