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/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 = null) {
200
- if (null === options) {
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
- console.log("QuickJS Log:", ...nativeArgs);
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
- console.log("QuickJS console.error:", ...nativeArgs);
266
+ logger.error(nativeArgs, "sandbox");
236
267
  lastError = JSON.stringify(nativeArgs);
237
268
  errorState = true;
238
269
  } catch (e) {
239
- console.log("Error in error:", e);
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
- runTask: (task) => {
312
+ // make sure code passes the typescript compilation
313
+ checkCode: (code) => {
314
+ logger.clear();
282
315
  try {
283
- const compiled = tsCompile(task);
316
+ const compiled = tsCompile(code);
284
317
  if (!compiled || compiled.length === 0) {
285
- console.error("Could not compile", task);
286
- return false;
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
- for (let i = 0; i < lines.length; i++) {
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 false;
298
- } else {
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
- for (let i = 0; i < lines.length; i++) {
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 !errorState;
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
- console.log(e);
375
+ logger.error(["Error running code:", e], "runner");
310
376
  }
311
- return false;
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
- apiKey: process.env.OPENAI_API_KEY
319
- // This is also the default, can be omitted
320
- });
321
- function createBasePrompt(apiFilePath, documentationPath) {
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 generateCode = async function(queryText, userChatHistory, createTaskPrompt, debug = false, model = "gpt-4o-mini") {
328
- if (!queryText)
329
- return { code: "", loggableCode: "" };
330
- const prompt = createTaskPrompt.replace("{{QUERY_TEXT}}", queryText);
331
- const messages = [
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
- role: "system",
334
- content: prompt
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
- role: "user",
339
- content: `${queryText}. Respond with json`,
340
- name: "user"
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 results = await openai.chat.completions.create(
345
- {
346
- model,
347
- messages,
348
- temperature: 0,
349
- max_tokens: 2e3,
350
- response_format: {
351
- json_schema: {
352
- name: "codeResponse",
353
- description: "The code generated by the AI",
354
- schema: {
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
- if (debug)
369
- console.log(results.usage);
370
- const response = results.choices[0].message.content;
371
- if (debug)
372
- console.log(response);
373
- try {
374
- const json = JSON.parse(response);
375
- const code = json.yourCode.replaceAll("```", "");
376
- return { code, loggableCode: code };
377
- } catch (err) {
378
- console.error("Error parsing response", err);
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 { code: "", loggableCode: "" };
519
+ return null;
384
520
  }
385
521
  };
386
- let QuickJS = null;
387
522
  async function createWithAPI(options) {
388
- options = {
389
- apiGlobalName: "api",
390
- apiGlobals: {},
391
- apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
392
- debug: false,
393
- model: "gpt-4o-mini",
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 (!options.apiObject || !options.apiDefFilePath) {
397
- throw new Error("apiObject and apiFilePath are required");
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 } = options;
400
- const createTaskPrompt = createBasePrompt(apiDefFilePath, apiDocsPath);
401
- return {
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 { code: "", loggableCode: "" };
406
- return await generateCode(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), debug, model);
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
- runCode: async function(generatedCode) {
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
- for (const key in options.apiGlobals) {
416
- apiGlobals[key] = {
417
- value: options.apiGlobals[key]
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
- const { vm, runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, {
421
- [apiDefFilePath.replaceAll("\\", "")]: apiExports
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", generatedCode);
641
+ console.log("Running Code:\n", code);
432
642
  }
433
- const res = await runTask(generatedCode.replace("'api.ts'", `'${options.apiDefFilePath}'`));
643
+ const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
434
644
  if (!res) {
435
- console.error("Task unsuccessful");
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(userQuery, [], createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""));
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
- await this.runCode(generatedCode.code.replace("'api.ts'", `'${options.apiDefFilePath}'`));
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 };
@@ -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: "api", // Should match whatever you declared as your global in your api.
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: true,
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
- // console.log("Print 'hello' three times.")
21
- // await aimyapi.processRequest("Print 'hello' three times.");
22
+ console.log("Print 'hello' three times.")
23
+ await aimyapi.processRequest("Print 'hello' three times.");
22
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
+ 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
- // console.log("Which business unit had the highest sales in 2020?")
27
- // await aimyapi.processRequest("Which business unit had the highest sales in 2020?");
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");
@@ -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, GenerateCodeResult } from "../src";
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 api = new OrderingAPI();
12
+ const orderingApi = new OrderingAPI();
12
13
 
13
14
  const options = {
14
- apiObject: api,
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:GenerateCodeResult = await aimyapi.generateCode(query, api._getHistory());
28
-
29
- api._addMessageToHistory({
30
- content: query,
31
- role: "user",
32
- name: "user",
33
- });
34
-
35
- api._addMessageToHistory({
36
- content: '```\n' + codeResult.loggableCode + '\n```',
37
- role: "assistant",
38
- name: "assistant",
39
- });
40
-
41
- // run the code in the sandbox
42
- await aimyapi.runCode(codeResult.code);
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?");