aimyapi 1.0.2 → 1.0.4
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 +3 -6
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/index.mjs +5 -5
- package/example/example1.ts +0 -2
- package/example/example2.ts +2 -3
- package/example/example3.ts +2 -3
- package/package.json +1 -1
- package/src/index.ts +7 -7
package/README.md
CHANGED
|
@@ -8,16 +8,13 @@ AIMyAPI will handle async operations and timers in your API object.
|
|
|
8
8
|
|
|
9
9
|
## About version 1.0 rewrite and motivation
|
|
10
10
|
|
|
11
|
-
AIMyAPI was originally written at a time (circa ChatGPT 3.5 / GPT-4) before tool calling existed, before Claude code and codex and just before OpenAI released their code interpreter. LLM models have also gotten drastically better since. Some of the problems it originally aimed to solve are better solved today with simple tool calling. However, there is still a need to safely run small programs in a sandboxed way, reliable way. Tools are good if you have a set interface but there may be times that an agent needs to do some sorting or filtering, or an algorithm or analysis, or some repeatable workflow which isn't implemented by the available tool functions. Writing code allows the agent to do things it might not otherwise be able to do with tools alone.
|
|
11
|
+
AIMyAPI was originally written at a time (circa ChatGPT 3.5 / GPT-4) before tool calling existed, before Claude code and codex and just before OpenAI released their code interpreter. LLM models have also gotten drastically better since. Some of the problems it originally aimed to solve are better solved today with simple tool calling. However, there is still a need to safely run small programs in a sandboxed way, reliable way. Tools are good if you have a set interface but there may be times that an agent needs to do some sorting or filtering, or an algorithm or analysis, or some repeatable workflow which isn't implemented by the available tool functions. Writing code allows the agent to do things it might not otherwise be able to do with tools alone. Having the ability to write code allows the tools API surface to be smaller; it could simply be a set of CRUD operations.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
The other advantage of writing code is privacy and security. When an agent executes code in a sandbox, it doesn't see any of the results*, API keys or other things you may want to keep hidden. When an agent uses tools, it sees all the parameters and results of the tool calls. Code can be audited for security and correctness before running it. Finally, code can encompass a series of operations, whereas tool calls need to be approved one at a time or just trusted often without knowing what will come next.
|
|
16
|
-
|
|
17
|
-
*You'll have the option to hide logs and errors from the agent - logging can allow the agent to fix it's own coding mistakes and test the code, but it also allows information to leave the sandbox which you may want to limit depending on the sensitivity the data your api is handling. Another approach would be to implement a mocked version of your API that the agent can use to write code and debug against while keeping your real data hidden and safe from potentially destructive operations.
|
|
13
|
+
The other advantage of writing code is privacy and security. When an agent executes code in a sandbox, it doesn't see any of the results*, API keys or other things you may want to keep hidden. When an agent uses tools, it sees all the parameters and results of the tool calls. Code can be audited for security and correctness before running it. Finally, code can encompass a series of operations, whereas tool calls need to be approved one at a time or just trusted, often without knowing what will come next.
|
|
18
14
|
|
|
19
15
|
Version 1.0 updates AIMyAPI code generation to use the tool calling process for writing code. This allows the agent to check the code and run some tests or API calls before committing to a final version. This should result in better code since the previous model relied on the agent always being able to one-shot the code, which depended on it having a complete view of the problem before writing the code which wasn't always realistic. We could also update this process a bit to add "Plan" / "Build" / "Test" phases instead of just one code generation prompt.
|
|
20
16
|
|
|
17
|
+
*You'll have the option to hide logs and errors from the agent - logging can allow the agent to fix it's own coding mistakes and test the code, but it also allows information to leave the sandbox which you may want to limit depending on the sensitivity the data your api is handling. Another approach would be to implement a mocked version of your API that the agent can use to write code and debug against while keeping your real data hidden and safe from potentially destructive operations.
|
|
21
18
|
|
|
22
19
|
## Quickstart
|
|
23
20
|
|
package/dist/index.cjs
CHANGED
|
@@ -405,7 +405,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
require$1("dotenv").config();
|
|
408
|
-
const openai = new openai$1.OpenAI();
|
|
408
|
+
const openai = new openai$1.OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
|
|
409
409
|
let QuickJS = null;
|
|
410
410
|
const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
|
|
411
411
|
(async () => {
|
|
@@ -590,9 +590,9 @@ async function createWithAPI(options) {
|
|
|
590
590
|
};
|
|
591
591
|
}
|
|
592
592
|
}
|
|
593
|
-
const { vm, checkCode } = await createSandbox(QuickJS, {
|
|
593
|
+
const { vm, checkCode } = await createSandbox(QuickJS, apiExports ? {
|
|
594
594
|
[apiDefFilePath]: apiExports
|
|
595
|
-
}, {
|
|
595
|
+
} : void 0, {
|
|
596
596
|
...apiGlobals,
|
|
597
597
|
[apiGlobalName]: {
|
|
598
598
|
value: apiObject,
|
|
@@ -649,9 +649,9 @@ async function createWithAPI(options) {
|
|
|
649
649
|
};
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
|
-
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, {
|
|
652
|
+
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
|
|
653
653
|
[apiDefFilePath]: apiExports
|
|
654
|
-
}, {
|
|
654
|
+
} : void 0, {
|
|
655
655
|
...apiGlobals,
|
|
656
656
|
[apiGlobalName]: {
|
|
657
657
|
value: apiObject,
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -405,7 +405,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
require$1("dotenv").config();
|
|
408
|
-
const openai = new openai$1.OpenAI();
|
|
408
|
+
const openai = new openai$1.OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
|
|
409
409
|
let QuickJS = null;
|
|
410
410
|
const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
|
|
411
411
|
(async () => {
|
|
@@ -590,9 +590,9 @@ async function createWithAPI(options) {
|
|
|
590
590
|
};
|
|
591
591
|
}
|
|
592
592
|
}
|
|
593
|
-
const { vm, checkCode } = await createSandbox(QuickJS, {
|
|
593
|
+
const { vm, checkCode } = await createSandbox(QuickJS, apiExports ? {
|
|
594
594
|
[apiDefFilePath]: apiExports
|
|
595
|
-
}, {
|
|
595
|
+
} : void 0, {
|
|
596
596
|
...apiGlobals,
|
|
597
597
|
[apiGlobalName]: {
|
|
598
598
|
value: apiObject,
|
|
@@ -649,9 +649,9 @@ async function createWithAPI(options) {
|
|
|
649
649
|
};
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
|
-
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, {
|
|
652
|
+
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
|
|
653
653
|
[apiDefFilePath]: apiExports
|
|
654
|
-
}, {
|
|
654
|
+
} : void 0, {
|
|
655
655
|
...apiGlobals,
|
|
656
656
|
[apiGlobalName]: {
|
|
657
657
|
value: apiObject,
|
package/dist/index.mjs
CHANGED
|
@@ -383,7 +383,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
require$1("dotenv").config();
|
|
386
|
-
const openai = new OpenAI();
|
|
386
|
+
const openai = new OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
|
|
387
387
|
let QuickJS = null;
|
|
388
388
|
const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
|
|
389
389
|
(async () => {
|
|
@@ -568,9 +568,9 @@ async function createWithAPI(options) {
|
|
|
568
568
|
};
|
|
569
569
|
}
|
|
570
570
|
}
|
|
571
|
-
const { vm, checkCode } = await createSandbox(QuickJS, {
|
|
571
|
+
const { vm, checkCode } = await createSandbox(QuickJS, apiExports ? {
|
|
572
572
|
[apiDefFilePath]: apiExports
|
|
573
|
-
}, {
|
|
573
|
+
} : void 0, {
|
|
574
574
|
...apiGlobals,
|
|
575
575
|
[apiGlobalName]: {
|
|
576
576
|
value: apiObject,
|
|
@@ -627,9 +627,9 @@ async function createWithAPI(options) {
|
|
|
627
627
|
};
|
|
628
628
|
}
|
|
629
629
|
}
|
|
630
|
-
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, {
|
|
630
|
+
const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
|
|
631
631
|
[apiDefFilePath]: apiExports
|
|
632
|
-
}, {
|
|
632
|
+
} : void 0, {
|
|
633
633
|
...apiGlobals,
|
|
634
634
|
[apiGlobalName]: {
|
|
635
635
|
value: apiObject,
|
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;
|
|
@@ -11,7 +10,6 @@ import { API } from "./sales_api_impl";
|
|
|
11
10
|
const aimyapi = await AIMyAPI.createWithAPI({
|
|
12
11
|
apiObject: api,
|
|
13
12
|
apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
|
|
14
|
-
apiExports: APIExports,
|
|
15
13
|
apiDefFilePath: path.join(__dirname, "./sales_api.ts"),
|
|
16
14
|
apiDocsPath: path.join(__dirname, "./sales_api.md"),
|
|
17
15
|
debug: false,
|
package/example/example2.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { AIMyAPI } from "../src";
|
|
5
|
-
import
|
|
5
|
+
import { Menu } from "./ordering_api";
|
|
6
6
|
import { OrderingAPI } from "./ordering_api_impl";
|
|
7
7
|
|
|
8
8
|
// More complex fast food ordering example that uses chat history.
|
|
@@ -15,9 +15,8 @@ import { OrderingAPI } from "./ordering_api_impl";
|
|
|
15
15
|
apiObject: orderingApi,
|
|
16
16
|
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
17
17
|
apiGlobals: {
|
|
18
|
-
Menu:
|
|
18
|
+
Menu: Menu,
|
|
19
19
|
},
|
|
20
|
-
apiExports: APIExports,
|
|
21
20
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
22
21
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
23
22
|
debug: false,
|
package/example/example3.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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';
|
|
@@ -28,9 +28,8 @@ function getInput(query: string): Promise<string> {
|
|
|
28
28
|
apiObject: orderingApi,
|
|
29
29
|
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
30
30
|
apiGlobals: {
|
|
31
|
-
Menu:
|
|
31
|
+
Menu: Menu,
|
|
32
32
|
},
|
|
33
|
-
apiExports: APIExports,
|
|
34
33
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
35
34
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
36
35
|
debug: false,
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -13,13 +13,13 @@ import { AutoParseableTool } from 'openai/lib/parser.js';
|
|
|
13
13
|
import { ZodSchema, z } from 'zod';
|
|
14
14
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
15
15
|
|
|
16
|
-
const openai = new OpenAI();
|
|
16
|
+
const openai = new OpenAI( { baseURL: process.env.OPENAI_API_BASE_URL || undefined, apiKey: process.env.OPENAI_API_KEY || undefined } );
|
|
17
17
|
|
|
18
18
|
let QuickJS:QuickJSWASMModule | null = null;
|
|
19
19
|
|
|
20
20
|
export interface AIMyAPIOptions {
|
|
21
21
|
apiObject: object;
|
|
22
|
-
apiExports
|
|
22
|
+
apiExports?: object;
|
|
23
23
|
apiWhitelist?: string[]; // List of functions to expose to the user. Necessary to pass this yourself if you are extending your api from another class.
|
|
24
24
|
apiGlobals?: object;
|
|
25
25
|
apiDefFilePath: string; // Full path to the api definition file so that it can be loaded into the prompt
|
|
@@ -222,7 +222,7 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
222
222
|
apiGlobals: {},
|
|
223
223
|
apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
|
|
224
224
|
debug: false,
|
|
225
|
-
model: process.env.OPENAI_API_MODEL ||"gpt-5.4-mini",
|
|
225
|
+
model: process.env.OPENAI_API_MODEL || "gpt-5.4-mini",
|
|
226
226
|
additionalModelOptions: {},
|
|
227
227
|
hideLogsFromAgent: false,
|
|
228
228
|
},
|
|
@@ -274,9 +274,9 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
// Create sandbox
|
|
277
|
-
const {vm, checkCode} = await createSandbox(QuickJS, {
|
|
277
|
+
const {vm, checkCode} = await createSandbox(QuickJS, apiExports ? {
|
|
278
278
|
[apiDefFilePath]: apiExports,
|
|
279
|
-
}, {
|
|
279
|
+
} : undefined, {
|
|
280
280
|
...apiGlobals,
|
|
281
281
|
[apiGlobalName]: {
|
|
282
282
|
value: apiObject,
|
|
@@ -348,9 +348,9 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
348
348
|
|
|
349
349
|
// Create sandbox
|
|
350
350
|
// NOTE: not sure why I have to replace the backslash here
|
|
351
|
-
const {vm, runCode: runTask, isAsyncProcessRunning} = await createSandbox(QuickJS, {
|
|
351
|
+
const {vm, runCode: runTask, isAsyncProcessRunning} = await createSandbox(QuickJS, apiExports ? {
|
|
352
352
|
[apiDefFilePath]: apiExports,
|
|
353
|
-
}, {
|
|
353
|
+
} : undefined, {
|
|
354
354
|
...apiGlobals,
|
|
355
355
|
[apiGlobalName]: {
|
|
356
356
|
value: apiObject,
|