aimyapi 0.1.0
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/.prettierrc +3 -0
- package/LICENSE +21 -0
- package/README.md +197 -0
- package/dist/example/example1.d.ts +1 -0
- package/dist/example/example1.js +52 -0
- package/dist/example/example2.d.ts +1 -0
- package/dist/example/example2.js +66 -0
- package/dist/example/example3.d.ts +1 -0
- package/dist/example/example3.js +79 -0
- package/dist/example/ordering_api.d.ts +36 -0
- package/dist/example/ordering_api.js +125 -0
- package/dist/example/ordering_api_impl.d.ts +23 -0
- package/dist/example/ordering_api_impl.js +128 -0
- package/dist/example/sales_api.d.ts +16 -0
- package/dist/example/sales_api.js +5 -0
- package/dist/example/sales_api_impl.d.ts +7 -0
- package/dist/example/sales_api_impl.js +59 -0
- package/dist/lib/index.d.ts +26 -0
- package/dist/lib/index.js +179 -0
- package/dist/lib/sandbox-wrappers.d.ts +9 -0
- package/dist/lib/sandbox-wrappers.js +237 -0
- package/dist/lib/sandbox.d.ts +14 -0
- package/dist/lib/sandbox.js +161 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +7 -0
- package/example/example1.ts +33 -0
- package/example/example2.ts +50 -0
- package/example/example3.ts +64 -0
- package/example/ordering_api.md +106 -0
- package/example/ordering_api.ts +194 -0
- package/example/ordering_api_impl.ts +194 -0
- package/example/sales_api.md +15 -0
- package/example/sales_api.ts +29 -0
- package/example/sales_api_impl.ts +60 -0
- package/lib/index.ts +247 -0
- package/lib/sandbox-wrappers.ts +250 -0
- package/lib/sandbox.ts +184 -0
- package/lib/utils.ts +3 -0
- package/package.json +41 -0
- package/prompts/create-task-prompt.md +21 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import "quickjs-emscripten";
|
|
2
|
+
import { QuickJSDeferredPromise } from "quickjs-emscripten";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
let promiseId = 0;
|
|
6
|
+
let openPromises = {};
|
|
7
|
+
|
|
8
|
+
export function wrapPromise(vm, promise: Promise<any>, beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
9
|
+
promiseId += 1;
|
|
10
|
+
|
|
11
|
+
const vmPromise = vm.newPromise()
|
|
12
|
+
vmPromise._promiseId = promiseId;
|
|
13
|
+
beginAsyncProcess();
|
|
14
|
+
promise.then((...args) => {
|
|
15
|
+
//console.log("Promised resolved", args);
|
|
16
|
+
endAsyncProcess();
|
|
17
|
+
const wrappedArgs = args.map((arg) => wrap(vm, arg, undefined, beginAsyncProcess, endAsyncProcess));
|
|
18
|
+
openPromises[vmPromise._promiseId] = null;
|
|
19
|
+
vmPromise.resolve(...wrappedArgs);
|
|
20
|
+
wrappedArgs.forEach((arg) => arg.dispose());
|
|
21
|
+
}).catch((...args) => {
|
|
22
|
+
//console.log("Promised rejected", args);
|
|
23
|
+
const wrappedArgs = args.map((arg) => wrap(vm, arg, undefined, beginAsyncProcess, endAsyncProcess));
|
|
24
|
+
vmPromise.reject(...wrappedArgs);
|
|
25
|
+
wrappedArgs.forEach((arg) => arg.dispose());
|
|
26
|
+
openPromises[vmPromise._promiseId] = null;
|
|
27
|
+
});
|
|
28
|
+
vmPromise.settled.then( () => {
|
|
29
|
+
endAsyncProcess();
|
|
30
|
+
vm.runtime.executePendingJobs();
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
openPromises[promiseId] = vmPromise;
|
|
34
|
+
|
|
35
|
+
return vmPromise.handle
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function rejectOpenPromises(vm) {
|
|
39
|
+
for (const [id, promise ] of Object.entries(openPromises)) {
|
|
40
|
+
if (promise !== null) {
|
|
41
|
+
(promise as QuickJSDeferredPromise).reject(vm.newError("Shutting down"));
|
|
42
|
+
openPromises[id] = null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
vm.runtime.executePendingJobs();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function wrap(vm, value: any, context: object, beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
50
|
+
if (value === null) {
|
|
51
|
+
return null;
|
|
52
|
+
} else if (typeof value === 'object' && typeof value.then === 'function') {
|
|
53
|
+
//console.log("Wrapped promise");
|
|
54
|
+
return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess);
|
|
55
|
+
} else if (typeof value === "function") {
|
|
56
|
+
//console.log("Wrapped function")
|
|
57
|
+
return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess);
|
|
58
|
+
} else if (Array.isArray(value)) {
|
|
59
|
+
//console.log("Wrapped array")
|
|
60
|
+
return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess);
|
|
61
|
+
} else if (value === null) {
|
|
62
|
+
//console.log("Wrapped null")
|
|
63
|
+
return vm.null;
|
|
64
|
+
} else if (typeof value === "object") {
|
|
65
|
+
//console.log("Wrapped object")
|
|
66
|
+
return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess);
|
|
67
|
+
} else if (typeof value === "string") {
|
|
68
|
+
//console.log("Wrapped string")
|
|
69
|
+
return vm.newString(value)
|
|
70
|
+
} else if (typeof value === "number") {
|
|
71
|
+
//console.log("Wrapped number")
|
|
72
|
+
return vm.newNumber(value);
|
|
73
|
+
} else if (typeof value === "bigint") {
|
|
74
|
+
//console.log("Wrapped bigint")
|
|
75
|
+
return vm.newBigInt(value);
|
|
76
|
+
} else if (typeof value === "boolean") {
|
|
77
|
+
// since there is no newBoolean, we have to do this
|
|
78
|
+
return vm.evalCode(value ? "true" : "false").value;
|
|
79
|
+
} else if (typeof value === "undefined") {
|
|
80
|
+
return vm.undefined
|
|
81
|
+
} else {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function wrapObject(vm, obj: any, beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
87
|
+
const vmObject = vm.newObject();
|
|
88
|
+
|
|
89
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
90
|
+
//console.log("wrapping", key, value)
|
|
91
|
+
let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
|
|
92
|
+
|
|
93
|
+
if (wrappedValue !== null) {
|
|
94
|
+
vm.setProp(vmObject, key, wrappedValue);
|
|
95
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
|
|
96
|
+
wrappedValue.dispose();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return vmObject;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function wrapObjectWhitelist(vm, obj: any, whitelist: string[], beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
105
|
+
const vmObject = vm.newObject();
|
|
106
|
+
|
|
107
|
+
whitelist.forEach((key) => {
|
|
108
|
+
const value = obj[key];
|
|
109
|
+
//console.log("wrapping", key, value)
|
|
110
|
+
const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
|
|
111
|
+
|
|
112
|
+
if (wrappedValue !== null) {
|
|
113
|
+
vm.setProp(vmObject, key, wrappedValue);
|
|
114
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
|
|
115
|
+
wrappedValue.dispose();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return vmObject;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function wrapArray(vm, arr: any[], beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
124
|
+
const vmArray = vm.newArray();
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < arr.length; i++) {
|
|
127
|
+
let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess);
|
|
128
|
+
vm.setProp(vmArray, i, wrappedValue);
|
|
129
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null) {
|
|
130
|
+
wrappedValue.dispose();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return vmArray;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function wrapGenericFunction(vm, fn: Function, context: object = undefined, beginAsyncProcess: () => void, endAsyncProcess: () => void): any {
|
|
138
|
+
const vmFn = vm.newFunction(fn.name, (...args) => {
|
|
139
|
+
const unwrappedArgs: any[] = args.map(vm.dump)
|
|
140
|
+
//console.log("Wrapped function called", fn.name, unwrappedArgs )
|
|
141
|
+
try {
|
|
142
|
+
const result = fn.call(context, ...unwrappedArgs);
|
|
143
|
+
//console.log("result", result);
|
|
144
|
+
const wrappedResult = wrap(vm, result, undefined, beginAsyncProcess, endAsyncProcess);
|
|
145
|
+
return wrappedResult;
|
|
146
|
+
} catch (e) {
|
|
147
|
+
console.log("Error", e);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
});
|
|
151
|
+
return vmFn;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function injectTimingFunctions(vm, cbAddedTimer, cbRemovedTimer, maxTimeout = 600000): void {
|
|
155
|
+
// Should we impose a limit on how long things can run for?
|
|
156
|
+
const timeoutFunctionHandles = {};
|
|
157
|
+
const _setTimeout = vm.newFunction("setTimeout", (vmFnHandle, timeoutHandle) => {
|
|
158
|
+
// Make a copy because otherwise vmFnHandle does not live long enough to call after the timeout
|
|
159
|
+
const vmFnHandleCopy = vmFnHandle.dup()
|
|
160
|
+
let timeout = vm.dump(timeoutHandle)
|
|
161
|
+
|
|
162
|
+
// cap timeout at max timeout
|
|
163
|
+
if(timeout > maxTimeout) {
|
|
164
|
+
timeout = maxTimeout;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// console.log("Sandbox calling timeout for: " + timeout);
|
|
168
|
+
cbAddedTimer();
|
|
169
|
+
const timeoutID = setTimeout(() => {
|
|
170
|
+
timeoutFunctionHandles[timeoutID.toString()] = null;
|
|
171
|
+
// callFunction(vmFnHandleCopy) will call the vm function
|
|
172
|
+
// in the context of the vm
|
|
173
|
+
// we pass vm.undefined because we need to pass something for the "this" argument
|
|
174
|
+
//console.log("Sandbox called timeout function")
|
|
175
|
+
cbRemovedTimer();
|
|
176
|
+
vm.callFunction(vmFnHandleCopy, vm.undefined)
|
|
177
|
+
vmFnHandleCopy.dispose()
|
|
178
|
+
vm.runtime.executePendingJobs();
|
|
179
|
+
}, timeout)
|
|
180
|
+
timeoutFunctionHandles[timeoutID.toString()] = vmFnHandleCopy;
|
|
181
|
+
|
|
182
|
+
return vm.newNumber(timeoutID);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
vm.setProp(vm.global, "setTimeout", _setTimeout);
|
|
186
|
+
_setTimeout.dispose();
|
|
187
|
+
const intervalFunctionHandles = {};
|
|
188
|
+
const _setInterval = vm.newFunction("setInterval", (vmFnHandle, timeoutHandle) => {
|
|
189
|
+
// Make a copy because otherwise vmFnHandle does not live long enough to call after the timeout
|
|
190
|
+
const vmFnHandleCopy = vmFnHandle.dup()
|
|
191
|
+
let timeout = vm.dump(timeoutHandle)
|
|
192
|
+
|
|
193
|
+
// cap timeout at max timeout
|
|
194
|
+
if(timeout > maxTimeout) {
|
|
195
|
+
timeout = maxTimeout;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
//console.log("Sandbox calling interval for: " + timeout);
|
|
199
|
+
const maxRepetitions = 99;
|
|
200
|
+
let repetitions = 0;
|
|
201
|
+
cbAddedTimer();
|
|
202
|
+
const intervalId = setInterval(() => {
|
|
203
|
+
repetitions += 1;
|
|
204
|
+
intervalFunctionHandles[intervalId.toString()] = null
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
// callFunction(vmFnHandleCopy) will call the vm function
|
|
208
|
+
// in the context of the vm
|
|
209
|
+
// we pass vm.undefined because we need to pass something for the "this" argument
|
|
210
|
+
vm.callFunction(vmFnHandleCopy, vm.undefined)
|
|
211
|
+
vm.runtime.executePendingJobs();
|
|
212
|
+
|
|
213
|
+
if (repetitions > maxRepetitions) {
|
|
214
|
+
console.log("Sandbox interval exceeded max repetitions");
|
|
215
|
+
clearInterval(intervalId);
|
|
216
|
+
cbRemovedTimer();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
}, timeout);
|
|
220
|
+
intervalFunctionHandles[intervalId.toString()] = vmFnHandleCopy;
|
|
221
|
+
|
|
222
|
+
return vm.newNumber(intervalId);
|
|
223
|
+
});
|
|
224
|
+
vm.setProp(vm.global, "setInterval", _setInterval);
|
|
225
|
+
_setInterval.dispose();
|
|
226
|
+
|
|
227
|
+
const _clearTimeout = vm.newFunction("clearTimeout", (timeoutIdHandle) => {
|
|
228
|
+
const timeoutId = vm.dump(timeoutIdHandle);
|
|
229
|
+
const timeoutHandle = timeoutFunctionHandles[timeoutId.toString()];
|
|
230
|
+
if (timeoutHandle) {
|
|
231
|
+
cbRemovedTimer();
|
|
232
|
+
timeoutHandle.dispose();
|
|
233
|
+
clearTimeout(timeoutId);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
vm.setProp(vm.global, "clearTimeout", _clearTimeout);
|
|
237
|
+
_clearTimeout.dispose();
|
|
238
|
+
|
|
239
|
+
const _clearInterval = vm.newFunction("clearInterval", (intervalIdHandle) => {
|
|
240
|
+
const intervalId = vm.dump(intervalIdHandle);
|
|
241
|
+
const intervalHandle = intervalFunctionHandles[intervalId.toString()];
|
|
242
|
+
if (intervalId) {
|
|
243
|
+
cbRemovedTimer();
|
|
244
|
+
intervalHandle.dispose();
|
|
245
|
+
clearInterval(intervalId);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
vm.setProp(vm.global, "clearInterval", _clearInterval);
|
|
249
|
+
_clearInterval.dispose();
|
|
250
|
+
}
|
package/lib/sandbox.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import "quickjs-emscripten";
|
|
2
|
+
|
|
3
|
+
import * as ts from "typescript";
|
|
4
|
+
import {
|
|
5
|
+
injectTimingFunctions,
|
|
6
|
+
wrap,
|
|
7
|
+
wrapObject,
|
|
8
|
+
wrapObjectWhitelist,
|
|
9
|
+
} from "./sandbox-wrappers";
|
|
10
|
+
|
|
11
|
+
// Should we use "noEmitOnError": true ?
|
|
12
|
+
function tsCompile(
|
|
13
|
+
source: string,
|
|
14
|
+
options: ts.TranspileOptions = null
|
|
15
|
+
): string {
|
|
16
|
+
// Default options -- you could also perform a merge, or use the project tsconfig.json
|
|
17
|
+
if (null === options) {
|
|
18
|
+
options = {
|
|
19
|
+
compilerOptions: {
|
|
20
|
+
target: ts.ScriptTarget.ES2020,
|
|
21
|
+
module: ts.ModuleKind.None,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return ts.transpileModule(source, options).outputText;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface GlobalOption {
|
|
29
|
+
value: any;
|
|
30
|
+
whitelist?: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface Globals {
|
|
34
|
+
[key: string]: GlobalOption;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// function whitelist can be produced using something like:
|
|
38
|
+
// const assistantFunctions = Object.getOwnPropertyNames(Object.getPrototypeOf(apiObject))
|
|
39
|
+
// .filter((f) => f !== "constructor" && !f.startsWith("_"));
|
|
40
|
+
|
|
41
|
+
// Is there some way we can treat the API and globals the same?
|
|
42
|
+
// We could just provide an object for all globals (including the API) and also have the whitelist as a parameter..
|
|
43
|
+
export default async function createSandbox(QuickJS, requireLookup:any = {}, globals: Globals = {}, debug:boolean = false) {
|
|
44
|
+
const vm = QuickJS.newContext();
|
|
45
|
+
|
|
46
|
+
let errorState = false;
|
|
47
|
+
let lastError = "";
|
|
48
|
+
|
|
49
|
+
let asyncProcessesRunning = 0;
|
|
50
|
+
|
|
51
|
+
let beginAsyncProcess = () => {
|
|
52
|
+
asyncProcessesRunning++;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
let endAsyncProcess = () => {
|
|
56
|
+
if (asyncProcessesRunning > 0) {
|
|
57
|
+
asyncProcessesRunning--;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
let isAsyncProcessRunning = () => {
|
|
62
|
+
//console.log("asyncProcessesRunning:", asyncProcessesRunning);
|
|
63
|
+
return asyncProcessesRunning > 0;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// const assistantHandle = wrapObjectWhitelist(vm, apiObject, functionWhitelist, beginAsyncProcess, endAsyncProcess);
|
|
67
|
+
// vm.setProp(vm.global, apiGlobalName, assistantHandle)
|
|
68
|
+
|
|
69
|
+
// assistantHandle.dispose();
|
|
70
|
+
|
|
71
|
+
const logHandle = vm.newFunction("log", (...args) => {
|
|
72
|
+
const nativeArgs = args.map(vm.dump);
|
|
73
|
+
console.log("QuickJS Log:", ...nativeArgs);
|
|
74
|
+
});
|
|
75
|
+
const consoleHandle = vm.newObject();
|
|
76
|
+
const exportsHandle = vm.newObject();
|
|
77
|
+
|
|
78
|
+
const errorHandle = vm.newFunction("error", (...args) => {
|
|
79
|
+
try {
|
|
80
|
+
const nativeArgs = args.map(vm.dump);
|
|
81
|
+
|
|
82
|
+
console.log("QuickJS console.error:", ...nativeArgs);
|
|
83
|
+
lastError = JSON.stringify(nativeArgs);
|
|
84
|
+
errorState = true;
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.log("Error in error:", e);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const globalNames = Object.getOwnPropertyNames(globals);
|
|
91
|
+
for (let i = 0; i < globalNames.length; i++) {
|
|
92
|
+
const globalOption: GlobalOption = globals[globalNames[i]];
|
|
93
|
+
const globalObj = globalOption.whitelist
|
|
94
|
+
? wrapObjectWhitelist(
|
|
95
|
+
vm,
|
|
96
|
+
globalOption.value,
|
|
97
|
+
globalOption.whitelist,
|
|
98
|
+
beginAsyncProcess,
|
|
99
|
+
endAsyncProcess
|
|
100
|
+
)
|
|
101
|
+
: wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess);
|
|
102
|
+
|
|
103
|
+
vm.setProp(vm.global, globalNames[i], globalObj);
|
|
104
|
+
globalObj.dispose();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
injectTimingFunctions(vm, beginAsyncProcess, endAsyncProcess);
|
|
108
|
+
|
|
109
|
+
const requireHandle = vm.newFunction("require", (...args) => {
|
|
110
|
+
const nativeArgs = args.map(vm.dump);
|
|
111
|
+
if(requireLookup[nativeArgs[0] as string]) {
|
|
112
|
+
const returnObj = wrapObject(vm, requireLookup[nativeArgs[0] as string], beginAsyncProcess, endAsyncProcess);
|
|
113
|
+
return returnObj;
|
|
114
|
+
} else {
|
|
115
|
+
return vm.undefined;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
vm.setProp(consoleHandle, "log", logHandle);
|
|
120
|
+
vm.setProp(consoleHandle, "error", errorHandle);
|
|
121
|
+
vm.setProp(vm.global, "require", requireHandle);
|
|
122
|
+
vm.setProp(vm.global, "console", consoleHandle);
|
|
123
|
+
vm.setProp(vm.global, "exports", exportsHandle);
|
|
124
|
+
|
|
125
|
+
consoleHandle.dispose();
|
|
126
|
+
logHandle.dispose();
|
|
127
|
+
exportsHandle.dispose();
|
|
128
|
+
errorHandle.dispose();
|
|
129
|
+
requireHandle.dispose();
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
vm,
|
|
133
|
+
getLastError: () => {
|
|
134
|
+
return lastError;
|
|
135
|
+
},
|
|
136
|
+
isAsyncProcessRunning,
|
|
137
|
+
runTask: (task: string): boolean => {
|
|
138
|
+
try {
|
|
139
|
+
const compiled = tsCompile(task);
|
|
140
|
+
|
|
141
|
+
if (!compiled || compiled.length === 0) {
|
|
142
|
+
console.log("Could not compile");
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// View compiled typescript code for debugging
|
|
147
|
+
// if(debug)
|
|
148
|
+
// console.log(compiled);
|
|
149
|
+
|
|
150
|
+
errorState = false;
|
|
151
|
+
const result = vm.evalCode(compiled);
|
|
152
|
+
|
|
153
|
+
if (result.error) {
|
|
154
|
+
// log out the compiled program with line numbers
|
|
155
|
+
const lines = compiled.split("\n");
|
|
156
|
+
for (let i = 0; i < lines.length; i++) {
|
|
157
|
+
console.log(`${i + 1}: ${lines[i]}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log("Execution failed:", vm.dump(result.error));
|
|
161
|
+
|
|
162
|
+
result.error.dispose();
|
|
163
|
+
return false;
|
|
164
|
+
} else {
|
|
165
|
+
//console.log("Task Result:", vm.dump(result.value));
|
|
166
|
+
result.value.dispose();
|
|
167
|
+
|
|
168
|
+
if (errorState) {
|
|
169
|
+
const lines = compiled.split("\n");
|
|
170
|
+
for (let i = 0; i < lines.length; i++) {
|
|
171
|
+
console.log(`${i + 1}: ${lines[i]}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return !errorState;
|
|
176
|
+
}
|
|
177
|
+
} catch (e) {
|
|
178
|
+
console.log(e);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return false;
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
package/lib/utils.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aimyapi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI My API! Use LLMs to create small programs that safely* run and make calls against your API.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"directories": {
|
|
8
|
+
"lib": "lib"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"example1": "ts-node ./example/example1.ts",
|
|
12
|
+
"example2": "ts-node ./example/example2.ts",
|
|
13
|
+
"example3": "ts-node ./example/example3.ts",
|
|
14
|
+
"build": "tsc"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/WhiteNoise/aimyapi.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"AI",
|
|
22
|
+
"LLM",
|
|
23
|
+
"OpenAI"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"dotenv": "^16.0.3",
|
|
27
|
+
"openai": "^3.2.1",
|
|
28
|
+
"quickjs-emscripten": "^0.22.0",
|
|
29
|
+
"typescript": "^5.0.3"
|
|
30
|
+
},
|
|
31
|
+
"author": "David Wallin",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/WhiteNoise/aimyapi/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/WhiteNoise/aimyapi#readme",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^18.16.2",
|
|
39
|
+
"ts-node": "^10.9.1"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
You are an expert coder, writing typescript code to accomplish tasks for the user.
|
|
2
|
+
We fulfill user requests by writing code that does what the user asked by performing operations on an API.
|
|
3
|
+
Respond only with code - do not include any extra explanations or questions outside of the code.
|
|
4
|
+
if you need to talk to the user, do so using functions provided by the API.
|
|
5
|
+
You comment your code and are sure to properly escape your strings and follow good programming practices.
|
|
6
|
+
|
|
7
|
+
Here is the API that you will use:
|
|
8
|
+
|
|
9
|
+
`api.ts`:
|
|
10
|
+
```
|
|
11
|
+
{{API}}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Documentation:
|
|
15
|
+
|
|
16
|
+
{{DOCUMENTATION}}
|
|
17
|
+
|
|
18
|
+
Current Context:
|
|
19
|
+
```
|
|
20
|
+
{{CONTEXT}}
|
|
21
|
+
```
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2021" /* Node 16+ per https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping */,
|
|
4
|
+
"module": "nodenext" /* Some imports are really imports: https://www.typescriptlang.org/docs/handbook/esm-node.html */,
|
|
5
|
+
"moduleResolution": "nodenext" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
|
6
|
+
"lib": ["ES2021", "dom"] /* Specify library files to be included in the compilation. */,
|
|
7
|
+
"outDir": "dist" /* Redirect output structure to the directory. */,
|
|
8
|
+
"declaration": true
|
|
9
|
+
},
|
|
10
|
+
"include": ["**/*.ts"],
|
|
11
|
+
"exclude": ["**/node_modules"]
|
|
12
|
+
}
|