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/example/example2.ts
CHANGED
|
@@ -1,19 +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
|
|
3
|
-
import
|
|
4
|
+
import { AIMyAPI } from "../src";
|
|
5
|
+
import { Menu } 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.
|
|
16
|
-
|
|
17
|
+
apiGlobals: {
|
|
18
|
+
Menu: Menu,
|
|
19
|
+
},
|
|
17
20
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
18
21
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
19
22
|
debug: false,
|
|
@@ -24,22 +27,29 @@ import { OrderingAPI } from "./ordering_api_impl";
|
|
|
24
27
|
console.log(`Query: ${query}`)
|
|
25
28
|
|
|
26
29
|
// generate the code for this query
|
|
27
|
-
const codeResult
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
const codeResult = await aimyapi.generateCode(query, orderingApi._getHistory());
|
|
31
|
+
|
|
32
|
+
if(codeResult) {
|
|
33
|
+
orderingApi._addMessageToHistory({
|
|
34
|
+
content: query,
|
|
35
|
+
role: "user",
|
|
36
|
+
name: "user",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
orderingApi._addMessageToHistory({
|
|
40
|
+
content: codeResult.comments || "done",
|
|
41
|
+
role: "assistant",
|
|
42
|
+
name: "assistant",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// run the code in the sandbox
|
|
46
|
+
if(codeResult.code) {
|
|
47
|
+
await aimyapi.runCode(codeResult.code);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
console.error("No code generated for this query.");
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
}
|
|
44
54
|
|
|
45
55
|
await runQuery("How's the burger here?");
|
package/example/example3.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { AIMyAPI } from "../src";
|
|
4
|
-
import
|
|
4
|
+
import { Menu } from "./ordering_api";
|
|
5
5
|
import { OrderingAPI } from "./ordering_api_impl";
|
|
6
6
|
|
|
7
7
|
import readline from 'readline';
|
|
8
8
|
|
|
9
|
-
function getInput(query): Promise<string> {
|
|
9
|
+
function getInput(query: string): Promise<string> {
|
|
10
10
|
const rl = readline.createInterface({
|
|
11
11
|
input: process.stdin,
|
|
12
12
|
output: process.stdout,
|
|
@@ -20,14 +20,16 @@ function getInput(query): Promise<string> {
|
|
|
20
20
|
|
|
21
21
|
// More complex fast food ordering example that uses chat history.
|
|
22
22
|
// Fast food ordering example.
|
|
23
|
-
// Interactive version
|
|
23
|
+
// -- Interactive version
|
|
24
24
|
(async () => {
|
|
25
|
-
const
|
|
25
|
+
const orderingApi = new OrderingAPI();
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
|
-
apiObject:
|
|
28
|
+
apiObject: orderingApi,
|
|
29
29
|
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
30
|
-
|
|
30
|
+
apiGlobals: {
|
|
31
|
+
Menu: Menu,
|
|
32
|
+
},
|
|
31
33
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
32
34
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
33
35
|
debug: false,
|
|
@@ -38,26 +40,30 @@ function getInput(query): Promise<string> {
|
|
|
38
40
|
console.log(`Query: ${query}`)
|
|
39
41
|
|
|
40
42
|
// generate the code for this query
|
|
41
|
-
const result = await aimyapi.generateCode(query,
|
|
43
|
+
const result = await aimyapi.generateCode(query, orderingApi._getHistory());
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
if(result) {
|
|
46
|
+
orderingApi._addMessageToHistory({
|
|
47
|
+
content: query,
|
|
48
|
+
role: "user",
|
|
49
|
+
name: "user",
|
|
50
|
+
});
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
orderingApi._addMessageToHistory({
|
|
53
|
+
content: result.comments || "done",
|
|
54
|
+
role: "assistant",
|
|
55
|
+
name: "assistant",
|
|
56
|
+
});
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
// run the code in the sandbox
|
|
59
|
+
if(result.code) {
|
|
60
|
+
await aimyapi.runCode(result.code);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
console.log("Welcome to the restaurant. You can ask to hear the menu or order something. What would you like to do?");
|
|
60
|
-
while (!
|
|
66
|
+
while (!orderingApi._isCompleted) {
|
|
61
67
|
const query:string = await getInput("Your query: ");
|
|
62
68
|
await runQuery(query);
|
|
63
69
|
}
|
package/example/ordering_api.md
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
You work at a restaurant.
|
|
2
4
|
Your responses should be energetic, positive and polite.
|
|
3
5
|
Help the customer with whatever questions they may have and ring up their orders.
|
|
4
6
|
Do not complete the order until the user says they are finished ordering.
|
|
5
7
|
Your code should check for errors or for cases where items may not be found.
|
|
6
8
|
|
|
7
|
-
Examples of how you should respond:
|
|
9
|
+
## Examples of how you should respond:
|
|
8
10
|
|
|
9
11
|
user: How are you today?
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
+
code:
|
|
14
|
+
```typescript
|
|
13
15
|
orderingApi.respondToUser("I'm great, thanks for asking!");
|
|
14
16
|
```
|
|
15
17
|
|
|
16
18
|
user: Add a hamburger with no cheese to my order
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
+
code:
|
|
21
|
+
```typescript
|
|
20
22
|
const itemName = "Hamburger";
|
|
21
|
-
const item =
|
|
23
|
+
const item = Menu.find((item) => item.name === itemName);
|
|
22
24
|
if (!item) {
|
|
23
25
|
throw new Error(`Item with name "${itemName}" not found`);
|
|
24
26
|
}
|
|
@@ -31,18 +33,18 @@ log: Added Hamburger with id 1
|
|
|
31
33
|
|
|
32
34
|
user: I'd like a large pizza with mushrooms
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
+
code:
|
|
37
|
+
```typescript
|
|
36
38
|
orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
|
|
37
39
|
orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
|
|
38
40
|
```
|
|
39
41
|
|
|
40
42
|
user: Add a hamburger with bacon
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
+
code:
|
|
45
|
+
```typescript
|
|
44
46
|
const itemName = "Hamburger";
|
|
45
|
-
const item =
|
|
47
|
+
const item = Menu.find((item) => item.name === itemName);
|
|
46
48
|
if (!item) {
|
|
47
49
|
throw new Error(`Item with name "${itemName}" not found`);
|
|
48
50
|
}
|
|
@@ -55,8 +57,8 @@ log: Added Hamburger with id 2
|
|
|
55
57
|
|
|
56
58
|
user: Add jalapenos to that
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
+
code:
|
|
61
|
+
```typescript
|
|
60
62
|
const existingItem = orderingApi.getItemInOrder("2");
|
|
61
63
|
|
|
62
64
|
if(existingItem) {
|
|
@@ -69,10 +71,10 @@ if(existingItem) {
|
|
|
69
71
|
|
|
70
72
|
user: Add a hamburger with no lettuce
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
+
code:
|
|
75
|
+
```typescript
|
|
74
76
|
const itemName = "Hamburger";
|
|
75
|
-
const item =
|
|
77
|
+
const item = Menu.find((item) => item.name === itemName);
|
|
76
78
|
if (!item) {
|
|
77
79
|
throw new Error(`Item with name "${itemName}" not found`);
|
|
78
80
|
}
|
|
@@ -86,7 +88,7 @@ log: Added Hamburger with id 2
|
|
|
86
88
|
|
|
87
89
|
user: I want an elephant.
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
+
code:
|
|
92
|
+
```typescript
|
|
91
93
|
orderingApi.respondToUser("I'm sorry, but that isn't on our menu.");
|
|
92
94
|
```
|
package/example/ordering_api.ts
CHANGED
|
@@ -184,7 +184,8 @@ export interface OrderingAPIInterface {
|
|
|
184
184
|
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
-
// Global object
|
|
187
|
+
// Global object for accessing the OrderingAPIInterface
|
|
188
188
|
declare global {
|
|
189
|
-
|
|
189
|
+
const orderingApi: OrderingAPIInterface;
|
|
190
|
+
const Menu: MenuItemBase[];
|
|
190
191
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
OrderingAPIInterface,
|
|
8
8
|
} from "./ordering_api";
|
|
9
9
|
|
|
10
|
-
// TODO:
|
|
10
|
+
// TODO: Typescript typing could be better on this API and it would probably benefit the agent.
|
|
11
11
|
|
|
12
12
|
export class OrderingAPI implements OrderingAPIInterface {
|
|
13
13
|
private _order: MenuItemBase[] = [];
|
|
@@ -66,6 +66,7 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
66
66
|
throw new Error(`Item with name "${itemName}" not found`);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// FIXME: we shouldn't allow adding an item with customizations that aren't in the allowedCustomizations list for that item
|
|
69
70
|
const customizations = customizationNames ? customizationNames
|
|
70
71
|
.map((customizationName) => {
|
|
71
72
|
return this.getCustomizationByName(itemName, customizationName);
|
package/example/sales_api.md
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
## Examples:
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
to print hello:
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
assistant:
|
|
8
|
-
```
|
|
9
|
-
api.print("I'm great, thanks for asking!");
|
|
10
|
-
```
|
|
5
|
+
submitCode("salesApi.print(\"Hello\")");
|
package/example/sales_api.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aimyapi",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "AI My API!
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "AI My API! Typescript sandbox for AI agents to interact with your API in a safe way.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"module": "./dist/index.mjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
8
|
"exports": {
|
|
9
9
|
"require": {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
"types": "./dist/index.d.cts",
|
|
11
|
+
"default": "./dist/index.cjs"
|
|
12
12
|
},
|
|
13
13
|
"import": {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
"types": "./dist/index.d.mts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"directories": {
|
|
@@ -35,9 +35,11 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"dotenv": "^16.0.3",
|
|
38
|
-
"openai": "^
|
|
38
|
+
"openai": "^6.33.0",
|
|
39
39
|
"quickjs-emscripten": "^0.22.0",
|
|
40
|
-
"typescript": "^5.0.3"
|
|
40
|
+
"typescript": "^5.0.3",
|
|
41
|
+
"zod": "^3.23.8",
|
|
42
|
+
"zod-to-json-schema": "^3.23.3"
|
|
41
43
|
},
|
|
42
44
|
"author": "David Wallin",
|
|
43
45
|
"license": "MIT",
|
|
@@ -46,7 +48,7 @@
|
|
|
46
48
|
},
|
|
47
49
|
"homepage": "https://github.com/WhiteNoise/aimyapi#readme",
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@types/node": "^18.
|
|
51
|
+
"@types/node": "^18.19.130",
|
|
50
52
|
"pkgroll": "^2.5.0",
|
|
51
53
|
"tsx": "^4.19.1"
|
|
52
54
|
}
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
You are a helpful assistant who speaks only in Typescript.
|
|
2
|
-
You work just like a regular assistant, but you fulfill user requests by writing code.
|
|
3
|
-
You comment your code and are sure to properly escape your strings and follow good programming practices.
|
|
4
1
|
|
|
5
|
-
|
|
2
|
+
Most recent user query:
|
|
3
|
+
```
|
|
4
|
+
{{USER_QUERY}}
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Based on the above conversation, write a typescript script that performs the next operation requested by the user.
|
|
8
|
+
|
|
9
|
+
Here's the typescript API to use for your script.
|
|
6
10
|
|
|
7
11
|
`api.ts`:
|
|
8
|
-
```
|
|
12
|
+
```typescript
|
|
9
13
|
{{API}}
|
|
10
14
|
```
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
Use the global api object to make calls to the API.
|
|
17
|
+
You may use top level `await`.
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} catch(err) {
|
|
22
|
-
console.error(err);
|
|
23
|
-
}
|
|
24
|
-
})();
|
|
25
|
-
```
|
|
19
|
+
If needed, gather any information you need to complete the request.
|
|
20
|
+
You may use `runCode` to run any non-destructive API calls to understand what you need to do. Nothing will be returned unless you `console.log` it.
|
|
21
|
+
In your code, `console.log` and `console.error` can be used to understand the execution or indicate that an error happened, but debug logs should be removed in the final version.
|
|
22
|
+
You can use the `checkCode` tool to confirm that the code passes the typescript compilation and doesn't have errors
|
|
23
|
+
You can call `submitCode` to submit the final version of the code.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
26
|
|
|
27
27
|
{{DOCUMENTATION}}
|
|
28
28
|
|
|
29
|
-
Contextual data:
|
|
30
|
-
```
|
|
31
29
|
{{CONTEXT}}
|
|
32
|
-
|
|
30
|
+
|