aimyapi 0.2.1 → 1.0.3
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 +69 -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 -10
- package/example/example2.ts +32 -22
- package/example/example3.ts +26 -20
- 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 +325 -140
- 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,170 +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
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
(async() {
|
|
325
|
-
try {`;
|
|
326
|
-
const CODE_END = ` } catch(err) {
|
|
386
|
+
const openai = new OpenAI();
|
|
387
|
+
let QuickJS = null;
|
|
388
|
+
const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
|
|
389
|
+
(async () => {
|
|
390
|
+
try {
|
|
391
|
+
${code}
|
|
392
|
+
} catch(err) {
|
|
327
393
|
console.error(err);
|
|
328
394
|
}
|
|
329
395
|
})();
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
396
|
+
`;
|
|
397
|
+
const wrapCodeBlock = (code, codeType = "") => `
|
|
398
|
+
\`\`\`${codeType}
|
|
399
|
+
${code}
|
|
400
|
+
\`\`\`
|
|
401
|
+
`;
|
|
402
|
+
function zodParseJSON(schema) {
|
|
403
|
+
return (input) => schema.parse(JSON.parse(input));
|
|
334
404
|
}
|
|
335
|
-
function
|
|
336
|
-
const codeBlockRegex = /```[\s\S]*?```/g;
|
|
337
|
-
return text.replace(codeBlockRegex, (match) => {
|
|
338
|
-
const code = match.slice(3, -3).trim();
|
|
339
|
-
return `${CODE_START}
|
|
340
|
-
${indentString(code, 2)}
|
|
341
|
-
${CODE_END}`;
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
function createBasePrompt(apiFilePath, documentationPath) {
|
|
405
|
+
function createBasePrompt(apiFilePath, apiGlobalName, documentationPath) {
|
|
345
406
|
const apiText = fs.readFileSync(apiFilePath, "utf8");
|
|
346
407
|
const documentationText = documentationPath ? fs.readFileSync(documentationPath, "utf8") : "";
|
|
347
|
-
const createTaskPrompt = fs.readFileSync(path.join(__dirname, "../prompts/create-task-prompt.md"), "utf8").replace("{{DOCUMENTATION}}",
|
|
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 || "");
|
|
348
409
|
return createTaskPrompt;
|
|
349
410
|
}
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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 = [
|
|
355
426
|
{
|
|
356
|
-
|
|
357
|
-
|
|
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
|
+
},
|
|
446
|
+
{
|
|
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
|
+
}
|
|
358
462
|
},
|
|
359
|
-
...userChatHistory,
|
|
360
463
|
{
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
+
}
|
|
364
478
|
}
|
|
365
479
|
];
|
|
366
480
|
try {
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
type: "object",
|
|
379
|
-
properties: {
|
|
380
|
-
yourCode: {
|
|
381
|
-
type: "string",
|
|
382
|
-
description: "The code generated by the AI"
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
},
|
|
387
|
-
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)
|
|
388
492
|
}
|
|
493
|
+
],
|
|
494
|
+
tools: codingTools,
|
|
495
|
+
...additionalModelOptions
|
|
496
|
+
}).on("message", async (message) => {
|
|
497
|
+
if (debug) {
|
|
498
|
+
console.log("Message:", JSON.stringify(message, null, 2));
|
|
389
499
|
}
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
console.
|
|
402
|
-
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);
|
|
403
512
|
}
|
|
513
|
+
return {
|
|
514
|
+
code: finalSubmittedCode,
|
|
515
|
+
comments: finalContent || void 0
|
|
516
|
+
};
|
|
404
517
|
} catch (err) {
|
|
405
518
|
console.error(err);
|
|
406
|
-
return
|
|
519
|
+
return null;
|
|
407
520
|
}
|
|
408
521
|
};
|
|
409
|
-
let QuickJS = null;
|
|
410
522
|
async function createWithAPI(options) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
+
},
|
|
417
533
|
...options
|
|
418
534
|
};
|
|
419
|
-
if (!
|
|
420
|
-
throw new Error("apiObject and
|
|
535
|
+
if (!localOptions.apiObject || !localOptions.apiDefFilePath) {
|
|
536
|
+
throw new Error("apiObject and apiDefFilePath are required");
|
|
421
537
|
}
|
|
422
|
-
const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model } =
|
|
423
|
-
const createTaskPrompt = createBasePrompt(apiDefFilePath, apiDocsPath);
|
|
424
|
-
|
|
425
|
-
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,
|
|
426
542
|
generateCode: async function(queryText, userChatHistory, currentContext = void 0) {
|
|
427
543
|
if (!queryText)
|
|
428
|
-
return
|
|
429
|
-
|
|
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
|
+
);
|
|
430
556
|
},
|
|
431
|
-
|
|
557
|
+
checkCode: async function(generatedCode) {
|
|
432
558
|
if (!QuickJS) {
|
|
433
559
|
if (debug)
|
|
434
560
|
console.log("Creating quick.js");
|
|
435
561
|
QuickJS = await getQuickJS();
|
|
436
562
|
}
|
|
437
563
|
let apiGlobals = {};
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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]
|
|
441
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();
|
|
442
621
|
}
|
|
443
|
-
|
|
444
|
-
|
|
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
|
|
445
632
|
}, {
|
|
446
633
|
...apiGlobals,
|
|
447
634
|
[apiGlobalName]: {
|
|
@@ -451,11 +638,15 @@ async function createWithAPI(options) {
|
|
|
451
638
|
}, options.debug);
|
|
452
639
|
try {
|
|
453
640
|
if (debug) {
|
|
454
|
-
console.log("Running Code:\n",
|
|
641
|
+
console.log("Running Code:\n", code);
|
|
455
642
|
}
|
|
456
|
-
const res = await runTask(
|
|
643
|
+
const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
|
|
457
644
|
if (!res) {
|
|
458
|
-
console.error("
|
|
645
|
+
console.error("Unknown failure running task");
|
|
646
|
+
return {
|
|
647
|
+
success: false,
|
|
648
|
+
logs: []
|
|
649
|
+
};
|
|
459
650
|
}
|
|
460
651
|
while (isAsyncProcessRunning()) {
|
|
461
652
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -463,6 +654,7 @@ async function createWithAPI(options) {
|
|
|
463
654
|
if (debug) {
|
|
464
655
|
console.log("Completed");
|
|
465
656
|
}
|
|
657
|
+
return res;
|
|
466
658
|
} catch (err) {
|
|
467
659
|
if (debug) {
|
|
468
660
|
console.error("Error running task:", err);
|
|
@@ -471,20 +663,39 @@ async function createWithAPI(options) {
|
|
|
471
663
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
472
664
|
rejectOpenPromises(vm);
|
|
473
665
|
vm.dispose();
|
|
666
|
+
return {
|
|
667
|
+
success: false,
|
|
668
|
+
logs: []
|
|
669
|
+
};
|
|
474
670
|
},
|
|
671
|
+
// generates code and runs it in one step
|
|
475
672
|
processRequest: async function(userQuery, currentContext = void 0) {
|
|
476
673
|
if (debug) {
|
|
477
674
|
console.log("Query:", userQuery);
|
|
478
675
|
}
|
|
479
676
|
console.time("Generate Task");
|
|
480
|
-
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
|
+
);
|
|
481
687
|
console.timeEnd("Generate Task");
|
|
482
688
|
console.time("Run Code");
|
|
483
|
-
|
|
689
|
+
if (generatedCode?.code) {
|
|
690
|
+
await instance.runCode(generatedCode.code);
|
|
691
|
+
} else {
|
|
692
|
+
console.error("No code generated", generatedCode);
|
|
693
|
+
}
|
|
484
694
|
console.timeEnd("Run Code");
|
|
485
695
|
return generatedCode;
|
|
486
696
|
}
|
|
487
697
|
};
|
|
698
|
+
return instance;
|
|
488
699
|
}
|
|
489
700
|
const AIMyAPI = {
|
|
490
701
|
// Standard way of using the library
|
|
@@ -495,4 +706,4 @@ const AIMyAPI = {
|
|
|
495
706
|
createSandbox
|
|
496
707
|
};
|
|
497
708
|
|
|
498
|
-
export { AIMyAPI, createBasePrompt, generateCode };
|
|
709
|
+
export { AIMyAPI, createBasePrompt, generateCode, zodParseJSON };
|
package/example/example1.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { AIMyAPI } from "../src";
|
|
3
|
-
import * as APIExports from "./sales_api";
|
|
4
3
|
import { API } from "./sales_api_impl";
|
|
5
4
|
|
|
6
5
|
// Simpler example using no support for chat history;
|
|
@@ -10,21 +9,23 @@ import { API } from "./sales_api_impl";
|
|
|
10
9
|
|
|
11
10
|
const aimyapi = await AIMyAPI.createWithAPI({
|
|
12
11
|
apiObject: api,
|
|
13
|
-
apiGlobalName: "
|
|
14
|
-
apiExports: APIExports,
|
|
12
|
+
apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
|
|
15
13
|
apiDefFilePath: path.join(__dirname, "./sales_api.ts"),
|
|
16
14
|
apiDocsPath: path.join(__dirname, "./sales_api.md"),
|
|
17
|
-
debug:
|
|
15
|
+
debug: false,
|
|
18
16
|
})
|
|
17
|
+
|
|
18
|
+
aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
console.log("Print 'hello' three times.")
|
|
21
|
+
await aimyapi.processRequest("Print 'hello' three times.");
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
console.log("What month had the highest sales in 2020 for any business unit?")
|
|
24
|
+
await aimyapi.processRequest("What was our best month in 2020");
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
console.log("Which business unit had the highest sales in 2020? Print the totals for each")
|
|
27
|
+
await aimyapi.processRequest("Which business unit had the highest sales in 2020? Print the totals for each");
|
|
28
|
+
// 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
29
|
|
|
29
30
|
console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
|
|
30
31
|
await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
|