aimyapi 0.2.1 → 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/README.md +72 -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 -8
- package/example/example2.ts +31 -20
- package/example/example3.ts +25 -18
- 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 +324 -139
- package/src/sandbox.ts +119 -26
- package/tsconfig.json +1 -0
package/src/sandbox.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "quickjs-emscripten";
|
|
2
2
|
|
|
3
|
+
import { QuickJSWASMModule } from "quickjs-emscripten";
|
|
3
4
|
import * as ts from "typescript";
|
|
4
5
|
import {
|
|
5
6
|
injectTimingFunctions,
|
|
@@ -11,10 +12,10 @@ import {
|
|
|
11
12
|
// Should we use "noEmitOnError": true ?
|
|
12
13
|
function tsCompile(
|
|
13
14
|
source: string,
|
|
14
|
-
options
|
|
15
|
+
options?: ts.TranspileOptions
|
|
15
16
|
): string {
|
|
16
17
|
// Default options -- you could also perform a merge, or use the project tsconfig.json
|
|
17
|
-
if (
|
|
18
|
+
if (!options) {
|
|
18
19
|
options = {
|
|
19
20
|
compilerOptions: {
|
|
20
21
|
target: ts.ScriptTarget.ES2020,
|
|
@@ -34,13 +35,59 @@ export interface Globals {
|
|
|
34
35
|
[key: string]: GlobalOption;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
export type SandboxLog = {
|
|
39
|
+
type: "log" | "error";
|
|
40
|
+
args: any[];
|
|
41
|
+
source: string
|
|
42
|
+
};
|
|
43
|
+
export type CodeRunResult = {
|
|
44
|
+
success: boolean;
|
|
45
|
+
logs: SandboxLog[];
|
|
46
|
+
}
|
|
47
|
+
type LogSource = "sandbox" | "compiler" | "runner";
|
|
48
|
+
class Logger {
|
|
49
|
+
logs: SandboxLog[] = [];
|
|
50
|
+
debug: boolean = false;
|
|
51
|
+
|
|
52
|
+
constructor(debug: boolean = false) {
|
|
53
|
+
this.debug = debug;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
log(args: any, source: LogSource) {
|
|
57
|
+
if(Array.isArray(args)) {
|
|
58
|
+
this.logs.push({ type: "log", args, source });
|
|
59
|
+
} else {
|
|
60
|
+
this.logs.push({ type: "log", args: [args], source });
|
|
61
|
+
}
|
|
62
|
+
if (this.debug) {
|
|
63
|
+
console.log(`[${source}]:`, ...args);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
error(args: any, source: LogSource) {
|
|
68
|
+
if(Array.isArray(args)) {
|
|
69
|
+
this.logs.push({ type: "error", args, source });
|
|
70
|
+
} else {
|
|
71
|
+
this.logs.push({ type: "error", args: [args], source });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.error(`[${source}]:`, ...args);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
clear() {
|
|
78
|
+
this.logs = [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
37
84
|
// function whitelist can be produced using something like:
|
|
38
85
|
// const assistantFunctions = Object.getOwnPropertyNames(Object.getPrototypeOf(apiObject))
|
|
39
86
|
// .filter((f) => f !== "constructor" && !f.startsWith("_"));
|
|
40
87
|
|
|
41
88
|
// Is there some way we can treat the API and globals the same?
|
|
42
89
|
// 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) {
|
|
90
|
+
export default async function createSandbox(QuickJS: QuickJSWASMModule, requireLookup:any = {}, globals: Globals = {}, debug:boolean = false) {
|
|
44
91
|
const vm = QuickJS.newContext();
|
|
45
92
|
|
|
46
93
|
let errorState = false;
|
|
@@ -63,27 +110,31 @@ export default async function createSandbox(QuickJS, requireLookup:any = {}, glo
|
|
|
63
110
|
return asyncProcessesRunning > 0;
|
|
64
111
|
};
|
|
65
112
|
|
|
113
|
+
const logger = new Logger(debug);
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
66
117
|
// const assistantHandle = wrapObjectWhitelist(vm, apiObject, functionWhitelist, beginAsyncProcess, endAsyncProcess);
|
|
67
118
|
// vm.setProp(vm.global, apiGlobalName, assistantHandle)
|
|
68
119
|
|
|
69
120
|
// assistantHandle.dispose();
|
|
70
121
|
|
|
71
|
-
const logHandle = vm.newFunction("log", (...args) => {
|
|
122
|
+
const logHandle = vm.newFunction("log", (...args:any) => {
|
|
72
123
|
const nativeArgs = args.map(vm.dump);
|
|
73
|
-
|
|
124
|
+
logger.log(nativeArgs, "sandbox");
|
|
74
125
|
});
|
|
75
126
|
const consoleHandle = vm.newObject();
|
|
76
127
|
const exportsHandle = vm.newObject();
|
|
77
128
|
|
|
78
|
-
const errorHandle = vm.newFunction("error", (...args) => {
|
|
129
|
+
const errorHandle = vm.newFunction("error", (...args:any) => {
|
|
79
130
|
try {
|
|
80
131
|
const nativeArgs = args.map(vm.dump);
|
|
81
132
|
|
|
82
|
-
|
|
133
|
+
logger.error(nativeArgs, "sandbox");
|
|
83
134
|
lastError = JSON.stringify(nativeArgs);
|
|
84
135
|
errorState = true;
|
|
85
136
|
} catch (e) {
|
|
86
|
-
|
|
137
|
+
logger.error(["? Error in error:", e], "sandbox");
|
|
87
138
|
}
|
|
88
139
|
});
|
|
89
140
|
|
|
@@ -134,13 +185,42 @@ export default async function createSandbox(QuickJS, requireLookup:any = {}, glo
|
|
|
134
185
|
return lastError;
|
|
135
186
|
},
|
|
136
187
|
isAsyncProcessRunning,
|
|
137
|
-
|
|
188
|
+
// make sure code passes the typescript compilation
|
|
189
|
+
checkCode: (code: string) => {
|
|
190
|
+
logger.clear();
|
|
138
191
|
try {
|
|
139
|
-
const compiled = tsCompile(
|
|
192
|
+
const compiled = tsCompile(code);
|
|
193
|
+
if (!compiled || compiled.length === 0) {
|
|
194
|
+
logger.error(["Could not compile:", code], "compiler");
|
|
195
|
+
return {
|
|
196
|
+
success: false,
|
|
197
|
+
logs: logger.logs,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
} catch (e) {
|
|
201
|
+
logger.error(["Error testing code:", e], "compiler");
|
|
202
|
+
return {
|
|
203
|
+
success: false,
|
|
204
|
+
logs: logger.logs,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
logs: logger.logs,
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
runCode: (code: string): CodeRunResult => {
|
|
214
|
+
try {
|
|
215
|
+
logger.clear();
|
|
216
|
+
const compiled = tsCompile(code);
|
|
140
217
|
|
|
141
218
|
if (!compiled || compiled.length === 0) {
|
|
142
|
-
|
|
143
|
-
return
|
|
219
|
+
logger.error(["Could not compile:", code], "compiler");
|
|
220
|
+
return {
|
|
221
|
+
success: false,
|
|
222
|
+
logs: logger.logs,
|
|
223
|
+
};
|
|
144
224
|
}
|
|
145
225
|
|
|
146
226
|
// View compiled typescript code for debugging
|
|
@@ -152,33 +232,46 @@ export default async function createSandbox(QuickJS, requireLookup:any = {}, glo
|
|
|
152
232
|
|
|
153
233
|
if (result.error) {
|
|
154
234
|
// log out the compiled program with line numbers
|
|
155
|
-
const lines = compiled.split("\n");
|
|
156
|
-
|
|
157
|
-
console.log(`${i + 1}: ${lines[i]}`);
|
|
158
|
-
}
|
|
235
|
+
const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
|
|
236
|
+
|
|
159
237
|
|
|
160
|
-
|
|
238
|
+
logger.error(["Execution failed:", lines.join("\n"), vm.dump(result.error)], "runner");
|
|
161
239
|
|
|
162
240
|
result.error.dispose();
|
|
163
|
-
return
|
|
164
|
-
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
logs: logger.logs,
|
|
244
|
+
};
|
|
245
|
+
} else if("value" in result){
|
|
165
246
|
//console.log("Task Result:", vm.dump(result.value));
|
|
247
|
+
|
|
166
248
|
result.value.dispose();
|
|
167
249
|
|
|
250
|
+
|
|
168
251
|
if (errorState) {
|
|
169
|
-
const lines = compiled.split("\n");
|
|
170
|
-
|
|
171
|
-
console.log(`${i + 1}: ${lines[i]}`);
|
|
172
|
-
}
|
|
252
|
+
const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
|
|
253
|
+
logger.error(["An error was reported during execution. Compiled code with line numbers:", lines.join("\n")], "runner");
|
|
173
254
|
}
|
|
174
255
|
|
|
175
|
-
return
|
|
256
|
+
return {
|
|
257
|
+
success: !errorState,
|
|
258
|
+
logs: logger.logs,
|
|
259
|
+
};
|
|
260
|
+
} else {
|
|
261
|
+
logger.error(["Unknown execution result:", result], "runner");
|
|
262
|
+
return {
|
|
263
|
+
success: false,
|
|
264
|
+
logs: logger.logs,
|
|
265
|
+
};
|
|
176
266
|
}
|
|
177
267
|
} catch (e) {
|
|
178
|
-
|
|
268
|
+
logger.error(["Error running code:", e], "runner");
|
|
179
269
|
}
|
|
180
270
|
|
|
181
|
-
return
|
|
271
|
+
return {
|
|
272
|
+
success: false,
|
|
273
|
+
logs: logger.logs,
|
|
274
|
+
};
|
|
182
275
|
},
|
|
183
276
|
};
|
|
184
277
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
+
"rootDir": "./src",
|
|
3
4
|
"target": "ES2021" /* Node 16+ per https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping */,
|
|
4
5
|
"module": "nodenext" /* Some imports are really imports: https://www.typescriptlang.org/docs/handbook/esm-node.html */,
|
|
5
6
|
"moduleResolution": "nodenext" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|