aimyapi 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -416,11 +416,12 @@ const checkCodeSchema = z.object({
416
416
  const submitCodeSchema = z.object({
417
417
  code: z.string()
418
418
  });
419
- const generateCode = async function(instance, queryText, userChatHistory, createTaskPrompt, debug = false, hideLogsFromAgent = false, model = "gpt-5-mini", additionalModelOptions) {
419
+ const generateCode = async function(instance, queryText, userChatHistory, createTaskPrompt, debug = false, hideLogsFromAgent = false, model = "gpt-5-mini", additionalModelOptions, attempt = 0) {
420
420
  let finalSubmittedCode = "";
421
421
  if (debug) {
422
422
  console.log("Generating code for query:", queryText);
423
423
  }
424
+ const newHistoryItems = [];
424
425
  const codingTools = [
425
426
  {
426
427
  type: "function",
@@ -465,6 +466,14 @@ const generateCode = async function(instance, queryText, userChatHistory, create
465
466
  name: "submitCode",
466
467
  // @ts-ignore
467
468
  function: async ({ code }) => {
469
+ const checkRes = await instance.checkCode(code);
470
+ if (!checkRes.success) {
471
+ return {
472
+ success: false,
473
+ reason: "Code check failed",
474
+ logs: checkRes.logs
475
+ };
476
+ }
468
477
  finalSubmittedCode = code;
469
478
  return {
470
479
  success: true
@@ -487,7 +496,7 @@ const generateCode = async function(instance, queryText, userChatHistory, create
487
496
  ...userChatHistory,
488
497
  {
489
498
  role: "user",
490
- content: createTaskPrompt.replace("{{USER_QUERY}}", queryText)
499
+ content: attempt == 0 ? createTaskPrompt.replace("{{USER_QUERY}}", queryText) : queryText
491
500
  }
492
501
  ],
493
502
  tools: codingTools,
@@ -496,6 +505,7 @@ const generateCode = async function(instance, queryText, userChatHistory, create
496
505
  if (debug) {
497
506
  console.log("Message:", JSON.stringify(message, null, 2));
498
507
  }
508
+ newHistoryItems.push(message);
499
509
  }).on("functionToolCall", (functionCall) => {
500
510
  if (debug) {
501
511
  console.log("Function Call:", JSON.stringify(functionCall, null, 2));
@@ -507,15 +517,37 @@ const generateCode = async function(instance, queryText, userChatHistory, create
507
517
  });
508
518
  const finalContent = await runner.finalContent();
509
519
  if (debug) {
510
- console.log("Final Content:", finalContent);
520
+ console.log("Generate code final response:", finalContent);
521
+ }
522
+ if (!finalSubmittedCode) {
523
+ console.error("No code was submitted by the agent.");
524
+ if (attempt < 3) {
525
+ return generateCode(instance, `You must call submitCode with valid code before proceeding. Attempt ${attempt + 1} of 3.`, [
526
+ ...userChatHistory,
527
+ {
528
+ role: "user",
529
+ content: attempt == 0 ? createTaskPrompt.replace("{{USER_QUERY}}", queryText) : queryText
530
+ },
531
+ ...newHistoryItems
532
+ ], createTaskPrompt, debug, hideLogsFromAgent, model, additionalModelOptions, attempt + 1);
533
+ } else {
534
+ return {
535
+ success: false,
536
+ comments: "No code was submitted by the agent after multiple attempts. Final comment: " + finalContent
537
+ };
538
+ }
511
539
  }
512
540
  return {
541
+ success: true,
513
542
  code: finalSubmittedCode,
514
543
  comments: finalContent || void 0
515
544
  };
516
545
  } catch (err) {
517
546
  console.error(err);
518
- return null;
547
+ return {
548
+ success: false,
549
+ comments: `Error generating code: ${err}`
550
+ };
519
551
  }
520
552
  };
521
553
  async function createWithAPI(options) {
@@ -1,31 +1,31 @@
1
- import { AIMyAPI } from "../src";
2
- import { API } from "./sales_api_impl";
3
-
4
- // Simpler example using no support for chat history;
5
-
6
- (async () => {
7
- const api = new API();
8
-
9
- const aimyapi = await AIMyAPI.createWithAPI({
10
- apiObject: api,
11
- apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
12
- apiDefFilePath: "./example/sales_api.ts",
13
- apiDocsPath: "./example/sales_api.md",
14
- debug: false,
15
- })
16
-
17
- aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
18
-
19
- console.log("Print 'hello' three times.")
20
- await aimyapi.processRequest("Print 'hello' three times.");
21
-
22
- console.log("What month had the highest sales in 2020 for any business unit?")
23
- await aimyapi.processRequest("What was our best month in 2020");
24
-
25
- console.log("Which business unit had the highest sales in 2020? Print the totals for each")
26
- await aimyapi.processRequest("Which business unit had the highest sales in 2020? Print the totals for each");
27
- // 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
- console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
30
- await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
1
+ import { AIMyAPI } from "../src";
2
+ import { API } from "./sales_api_impl";
3
+
4
+ // Simpler example using no support for chat history;
5
+
6
+ (async () => {
7
+ const api = new API();
8
+
9
+ const aimyapi = await AIMyAPI.createWithAPI({
10
+ apiObject: api,
11
+ apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
12
+ apiDefFilePath: "./example/sales_api.ts",
13
+ apiDocsPath: "./example/sales_api.md",
14
+ debug: false,
15
+ })
16
+
17
+ aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
18
+
19
+ console.log("Print 'hello' three times.")
20
+ await aimyapi.processRequest("Print 'hello' three times.");
21
+
22
+ console.log("What month had the highest sales in 2020 for any business unit?")
23
+ await aimyapi.processRequest("What was our best month in 2020");
24
+
25
+ console.log("Which business unit had the highest sales in 2020? Print the totals for each")
26
+ await aimyapi.processRequest("Which business unit had the highest sales in 2020? Print the totals for each");
27
+ // 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
+ console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
30
+ await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
31
31
  })();
@@ -1,59 +1,59 @@
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
-
3
- import { AIMyAPI } from "../src";
4
- import { Menu } from "./ordering_api";
5
- import { OrderingAPI } from "./ordering_api_impl";
6
-
7
- // More complex fast food ordering example that uses chat history.
8
- // Fast food ordering example.
9
-
10
- (async () => {
11
- const orderingApi = new OrderingAPI();
12
-
13
- const options = {
14
- apiObject: orderingApi,
15
- apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
16
- apiGlobals: {
17
- Menu: Menu,
18
- },
19
- apiDefFilePath: "./example/ordering_api.ts",
20
- apiDocsPath: "./example/ordering_api.md",
21
- debug: false,
22
- };
23
- const aimyapi = await AIMyAPI.createWithAPI(options)
24
-
25
- async function runQuery(query:string) {
26
- console.log(`Query: ${query}`)
27
-
28
- // generate the code for this query
29
- const codeResult = await aimyapi.generateCode(query, orderingApi._getHistory());
30
-
31
- if(codeResult) {
32
- orderingApi._addMessageToHistory({
33
- content: query,
34
- role: "user",
35
- name: "user",
36
- });
37
-
38
- orderingApi._addMessageToHistory({
39
- content: codeResult.comments || "done",
40
- role: "assistant",
41
- name: "assistant",
42
- });
43
-
44
- // run the code in the sandbox
45
- if(codeResult.code) {
46
- await aimyapi.runCode(codeResult.code);
47
- }
48
- } else {
49
- console.error("No code generated for this query.");
50
- }
51
-
52
- }
53
-
54
- await runQuery("How's the burger here?");
55
- await runQuery("I'd like a plain hamburger (no cheese) and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.");
56
- await runQuery("I changed my mind, instead of anchovies, can I get a large gluten free pizza with pineapple instead.");
57
- await runQuery("email me the total at myemail@test.com and complete the order");
58
-
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
+
3
+ import { AIMyAPI } from "../src";
4
+ import { Menu } from "./ordering_api";
5
+ import { OrderingAPI } from "./ordering_api_impl";
6
+
7
+ // More complex fast food ordering example that uses chat history.
8
+ // Fast food ordering example.
9
+
10
+ (async () => {
11
+ const orderingApi = new OrderingAPI();
12
+
13
+ const options = {
14
+ apiObject: orderingApi,
15
+ apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
16
+ apiGlobals: {
17
+ Menu: Menu,
18
+ },
19
+ apiDefFilePath: "./example/ordering_api.ts",
20
+ apiDocsPath: "./example/ordering_api.md",
21
+ debug: false,
22
+ };
23
+ const aimyapi = await AIMyAPI.createWithAPI(options)
24
+
25
+ async function runQuery(query:string) {
26
+ console.log(`Query: ${query}`)
27
+
28
+ // generate the code for this query
29
+ const codeResult = await aimyapi.generateCode(query, orderingApi._getHistory());
30
+
31
+ if(codeResult) {
32
+ orderingApi._addMessageToHistory({
33
+ content: query,
34
+ role: "user",
35
+ name: "user",
36
+ });
37
+
38
+ orderingApi._addMessageToHistory({
39
+ content: codeResult.comments || "done",
40
+ role: "assistant",
41
+ name: "assistant",
42
+ });
43
+
44
+ // run the code in the sandbox
45
+ if(codeResult.code) {
46
+ await aimyapi.runCode(codeResult.code);
47
+ }
48
+ } else {
49
+ console.error("No code generated for this query.");
50
+ }
51
+
52
+ }
53
+
54
+ await runQuery("How's the burger here?");
55
+ await runQuery("I'd like a plain hamburger (no cheese) and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.");
56
+ await runQuery("I changed my mind, instead of anchovies, can I get a large gluten free pizza with pineapple instead.");
57
+ await runQuery("email me the total at myemail@test.com and complete the order");
58
+
59
59
  })();
@@ -1,70 +1,70 @@
1
-
2
- import { AIMyAPI } from "../src";
3
- import { Menu } from "./ordering_api";
4
- import { OrderingAPI } from "./ordering_api_impl";
5
-
6
- import readline from 'readline';
7
-
8
- function getInput(query: string): Promise<string> {
9
- const rl = readline.createInterface({
10
- input: process.stdin,
11
- output: process.stdout,
12
- });
13
-
14
- return new Promise(resolve => rl.question(query, ans => {
15
- rl.close();
16
- resolve(ans);
17
- }))
18
- }
19
-
20
- // More complex fast food ordering example that uses chat history.
21
- // Fast food ordering example.
22
- // -- Interactive version
23
- (async () => {
24
- const orderingApi = new OrderingAPI();
25
-
26
- const options = {
27
- apiObject: orderingApi,
28
- apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
29
- apiGlobals: {
30
- Menu: Menu,
31
- },
32
- apiDefFilePath: "./example/ordering_api.ts",
33
- apiDocsPath: "./example/ordering_api.md",
34
- debug: false,
35
- };
36
- const aimyapi = await AIMyAPI.createWithAPI(options)
37
-
38
- async function runQuery(query:string) {
39
- console.log(`Query: ${query}`)
40
-
41
- // generate the code for this query
42
- const result = await aimyapi.generateCode(query, orderingApi._getHistory());
43
-
44
- if(result) {
45
- orderingApi._addMessageToHistory({
46
- content: query,
47
- role: "user",
48
- name: "user",
49
- });
50
-
51
- orderingApi._addMessageToHistory({
52
- content: result.comments || "done",
53
- role: "assistant",
54
- name: "assistant",
55
- });
56
-
57
- // run the code in the sandbox
58
- if(result.code) {
59
- await aimyapi.runCode(result.code);
60
- }
61
- }
62
- }
63
-
64
- console.log("Welcome to the restaurant. You can ask to hear the menu or order something. What would you like to do?");
65
- while (!orderingApi._isCompleted) {
66
- const query:string = await getInput("Your query: ");
67
- await runQuery(query);
68
- }
69
-
1
+
2
+ import { AIMyAPI } from "../src";
3
+ import { Menu } from "./ordering_api";
4
+ import { OrderingAPI } from "./ordering_api_impl";
5
+
6
+ import readline from 'readline';
7
+
8
+ function getInput(query: string): Promise<string> {
9
+ const rl = readline.createInterface({
10
+ input: process.stdin,
11
+ output: process.stdout,
12
+ });
13
+
14
+ return new Promise(resolve => rl.question(query, ans => {
15
+ rl.close();
16
+ resolve(ans);
17
+ }))
18
+ }
19
+
20
+ // More complex fast food ordering example that uses chat history.
21
+ // Fast food ordering example.
22
+ // -- Interactive version
23
+ (async () => {
24
+ const orderingApi = new OrderingAPI();
25
+
26
+ const options = {
27
+ apiObject: orderingApi,
28
+ apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
29
+ apiGlobals: {
30
+ Menu: Menu,
31
+ },
32
+ apiDefFilePath: "./example/ordering_api.ts",
33
+ apiDocsPath: "./example/ordering_api.md",
34
+ debug: false,
35
+ };
36
+ const aimyapi = await AIMyAPI.createWithAPI(options)
37
+
38
+ async function runQuery(query:string) {
39
+ console.log(`Query: ${query}`)
40
+
41
+ // generate the code for this query
42
+ const result = await aimyapi.generateCode(query, orderingApi._getHistory());
43
+
44
+ if(result) {
45
+ orderingApi._addMessageToHistory({
46
+ content: query,
47
+ role: "user",
48
+ name: "user",
49
+ });
50
+
51
+ orderingApi._addMessageToHistory({
52
+ content: result.comments || "done",
53
+ role: "assistant",
54
+ name: "assistant",
55
+ });
56
+
57
+ // run the code in the sandbox
58
+ if(result.code) {
59
+ await aimyapi.runCode(result.code);
60
+ }
61
+ }
62
+ }
63
+
64
+ console.log("Welcome to the restaurant. You can ask to hear the menu or order something. What would you like to do?");
65
+ while (!orderingApi._isCompleted) {
66
+ const query:string = await getInput("Your query: ");
67
+ await runQuery(query);
68
+ }
69
+
70
70
  })();
@@ -1,94 +1,94 @@
1
- # Documentation
2
-
3
- You work at a restaurant.
4
- Your responses should be energetic, positive and polite.
5
- Help the customer with whatever questions they may have and ring up their orders.
6
- Do not complete the order until the user says they are finished ordering.
7
- Your code should check for errors or for cases where items may not be found.
8
-
9
- ## Examples of how you should respond:
10
-
11
- user: How are you today?
12
-
13
- code:
14
- ```typescript
15
- orderingApi.respondToUser("I'm great, thanks for asking!");
16
- ```
17
-
18
- user: Add a hamburger with no cheese to my order
19
-
20
- code:
21
- ```typescript
22
- const itemName = "Hamburger";
23
- const item = Menu.find((item) => item.name === itemName);
24
- if (!item) {
25
- throw new Error(`Item with name "${itemName}" not found`);
26
- }
27
-
28
- orderingApi.addItemToOrder(itemName, undefined, item.toppings.filter( topping => topping.name != "cheese") );
29
- orderingApi.respondToUser("Ok, I added a Hamburger. What else would you like?");
30
- ```
31
-
32
- log: Added Hamburger with id 1
33
-
34
- user: I'd like a large pizza with mushrooms
35
-
36
- code:
37
- ```typescript
38
- orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
39
- orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
40
- ```
41
-
42
- user: Add a hamburger with bacon
43
-
44
- code:
45
- ```typescript
46
- const itemName = "Hamburger";
47
- const item = Menu.find((item) => item.name === itemName);
48
- if (!item) {
49
- throw new Error(`Item with name "${itemName}" not found`);
50
- }
51
-
52
- orderingApi.addItemToOrder(itemName, undefined, [...item.toppings, "bacon"]);
53
- orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
54
- ```
55
-
56
- log: Added Hamburger with id 2
57
-
58
- user: Add jalapenos to that
59
-
60
- code:
61
- ```typescript
62
- const existingItem = orderingApi.getItemInOrder("2");
63
-
64
- if(existingItem) {
65
- orderingApi.modifyItemInOrder("2", existingItem.customizations.map(item => item.name), [...existingItem.toppings, "jalapenos"]);
66
- orderingApi.respondToUser("Ok, I added jalapenos to your Hamburger");
67
- } else {
68
- orderingApi.respondToUser("Hmm, I can't find that item.");
69
- }
70
- ```
71
-
72
- user: Add a hamburger with no lettuce
73
-
74
- code:
75
- ```typescript
76
- const itemName = "Hamburger";
77
- const item = Menu.find((item) => item.name === itemName);
78
- if (!item) {
79
- throw new Error(`Item with name "${itemName}" not found`);
80
- }
81
-
82
- orderingApi.addItemToOrder(itemName, undefined, [...item.toppings.filter(topping => topping != "lettuce")]);
83
- orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
84
- ```
85
-
86
- log: Added Hamburger with id 2
87
-
88
-
89
- user: I want an elephant.
90
-
91
- code:
92
- ```typescript
93
- orderingApi.respondToUser("I'm sorry, but that isn't on our menu.");
94
- ```
1
+ # Documentation
2
+
3
+ You work at a restaurant.
4
+ Your responses should be energetic, positive and polite.
5
+ Help the customer with whatever questions they may have and ring up their orders.
6
+ Do not complete the order until the user says they are finished ordering.
7
+ Your code should check for errors or for cases where items may not be found.
8
+
9
+ ## Examples of how you should respond:
10
+
11
+ user: How are you today?
12
+
13
+ code:
14
+ ```typescript
15
+ orderingApi.respondToUser("I'm great, thanks for asking!");
16
+ ```
17
+
18
+ user: Add a hamburger with no cheese to my order
19
+
20
+ code:
21
+ ```typescript
22
+ const itemName = "Hamburger";
23
+ const item = Menu.find((item) => item.name === itemName);
24
+ if (!item) {
25
+ throw new Error(`Item with name "${itemName}" not found`);
26
+ }
27
+
28
+ orderingApi.addItemToOrder(itemName, undefined, item.toppings.filter( topping => topping.name != "cheese") );
29
+ orderingApi.respondToUser("Ok, I added a Hamburger. What else would you like?");
30
+ ```
31
+
32
+ log: Added Hamburger with id 1
33
+
34
+ user: I'd like a large pizza with mushrooms
35
+
36
+ code:
37
+ ```typescript
38
+ orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
39
+ orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
40
+ ```
41
+
42
+ user: Add a hamburger with bacon
43
+
44
+ code:
45
+ ```typescript
46
+ const itemName = "Hamburger";
47
+ const item = Menu.find((item) => item.name === itemName);
48
+ if (!item) {
49
+ throw new Error(`Item with name "${itemName}" not found`);
50
+ }
51
+
52
+ orderingApi.addItemToOrder(itemName, undefined, [...item.toppings, "bacon"]);
53
+ orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
54
+ ```
55
+
56
+ log: Added Hamburger with id 2
57
+
58
+ user: Add jalapenos to that
59
+
60
+ code:
61
+ ```typescript
62
+ const existingItem = orderingApi.getItemInOrder("2");
63
+
64
+ if(existingItem) {
65
+ orderingApi.modifyItemInOrder("2", existingItem.customizations.map(item => item.name), [...existingItem.toppings, "jalapenos"]);
66
+ orderingApi.respondToUser("Ok, I added jalapenos to your Hamburger");
67
+ } else {
68
+ orderingApi.respondToUser("Hmm, I can't find that item.");
69
+ }
70
+ ```
71
+
72
+ user: Add a hamburger with no lettuce
73
+
74
+ code:
75
+ ```typescript
76
+ const itemName = "Hamburger";
77
+ const item = Menu.find((item) => item.name === itemName);
78
+ if (!item) {
79
+ throw new Error(`Item with name "${itemName}" not found`);
80
+ }
81
+
82
+ orderingApi.addItemToOrder(itemName, undefined, [...item.toppings.filter(topping => topping != "lettuce")]);
83
+ orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
84
+ ```
85
+
86
+ log: Added Hamburger with id 2
87
+
88
+
89
+ user: I want an elephant.
90
+
91
+ code:
92
+ ```typescript
93
+ orderingApi.respondToUser("I'm sorry, but that isn't on our menu.");
94
+ ```