aimyapi 1.0.8 → 1.0.10

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/src/sandbox.ts CHANGED
@@ -2,6 +2,7 @@ import "quickjs-emscripten";
2
2
 
3
3
  import { QuickJSWASMModule } from "quickjs-emscripten";
4
4
  import * as ts from "typescript";
5
+ import { Logger, SandboxLog } from "./logger";
5
6
  import {
6
7
  injectTimingFunctions,
7
8
  wrap,
@@ -34,51 +35,10 @@ export interface GlobalOption {
34
35
  export interface Globals {
35
36
  [key: string]: GlobalOption;
36
37
  }
37
-
38
- export type SandboxLog = {
39
- type: "log" | "error";
40
- args: any[];
41
- source: string
42
- };
43
38
  export type CodeRunResult = {
44
39
  success: boolean;
45
40
  logs: SandboxLog[];
46
41
  }
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
42
 
83
43
 
84
44
  // function whitelist can be produced using something like:
@@ -147,9 +107,10 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
147
107
  globalOption.value,
148
108
  globalOption.whitelist,
149
109
  beginAsyncProcess,
150
- endAsyncProcess
110
+ endAsyncProcess,
111
+ logger
151
112
  )
152
- : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess);
113
+ : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess, logger);
153
114
 
154
115
  vm.setProp(vm.global, globalNames[i], globalObj);
155
116
  globalObj.dispose();
@@ -160,7 +121,7 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
160
121
  const requireHandle = vm.newFunction("require", (...args) => {
161
122
  const nativeArgs = args.map(vm.dump);
162
123
  if(requireLookup[nativeArgs[0] as string]) {
163
- const returnObj = wrapObject(vm, requireLookup[nativeArgs[0] as string], beginAsyncProcess, endAsyncProcess);
124
+ const returnObj = wrapObject(vm, requireLookup[nativeArgs[0] as string], beginAsyncProcess, endAsyncProcess, logger);
164
125
  return returnObj;
165
126
  } else {
166
127
  return vm.undefined;
@@ -194,23 +155,23 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
194
155
  logger.error(["Could not compile:", code], "compiler");
195
156
  return {
196
157
  success: false,
197
- logs: logger.logs,
158
+ logs: logger.getLogs(),
198
159
  };
199
160
  }
200
161
  } catch (e) {
201
162
  logger.error(["Error testing code:", e], "compiler");
202
163
  return {
203
164
  success: false,
204
- logs: logger.logs,
165
+ logs: logger.getLogs(),
205
166
  };
206
167
  }
207
168
 
208
169
  return {
209
170
  success: true,
210
- logs: logger.logs,
171
+ logs: logger.getLogs(),
211
172
  }
212
173
  },
213
- runCode: (code: string): CodeRunResult => {
174
+ runCode: async (code: string): Promise<CodeRunResult> => {
214
175
  try {
215
176
  logger.clear();
216
177
  const compiled = tsCompile(code);
@@ -219,7 +180,7 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
219
180
  logger.error(["Could not compile:", code], "compiler");
220
181
  return {
221
182
  success: false,
222
- logs: logger.logs,
183
+ logs: logger.getLogs()
223
184
  };
224
185
  }
225
186
 
@@ -234,20 +195,36 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
234
195
  // log out the compiled program with line numbers
235
196
  const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
236
197
 
237
-
238
198
  logger.error(["Execution failed:", lines.join("\n"), vm.dump(result.error)], "runner");
239
199
 
240
200
  result.error.dispose();
241
201
  return {
242
202
  success: false,
243
- logs: logger.logs,
203
+ logs: logger.getPrettyLogs(),
244
204
  };
245
- } else if("value" in result){
246
- //console.log("Task Result:", vm.dump(result.value));
247
-
205
+ } else if("value" in result) {
206
+ //console.log("Task Result:", vm.dump(result.value), errorState);
207
+ // The wrapped code returns a promise; wait for it to settle.
208
+ const settled = vm.resolvePromise(result.value);
248
209
  result.value.dispose();
249
-
210
+ vm.runtime.executePendingJobs(); // start the async function running
211
+ const promiseResult = await settled;
212
+
213
+ if (promiseResult.error) {
214
+ const err = vm.dump(promiseResult.error);
215
+ promiseResult.error.dispose();
216
+ const lines = compiled.split("\n").map((l, i) => `${i + 1}: ${l}`);
217
+ logger.error(["Uncaught exception:", err, "\n", lines.join("\n")], "runner");
218
+ return {
219
+ success: false,
220
+ logs: logger.getPrettyLogs(),
221
+ };
222
+ }
223
+ // @ts-ignore this is a success response
224
+ promiseResult.value.dispose();
250
225
 
226
+
227
+
251
228
  if (errorState) {
252
229
  const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
253
230
  logger.error(["An error was reported during execution. Compiled code with line numbers:\n", lines.join("\n")], "runner");
@@ -255,13 +232,13 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
255
232
 
256
233
  return {
257
234
  success: !errorState,
258
- logs: logger.logs,
235
+ logs: logger.getPrettyLogs(),
259
236
  };
260
237
  } else {
261
238
  logger.error(["Unknown execution result:", result], "runner");
262
239
  return {
263
240
  success: false,
264
- logs: logger.logs,
241
+ logs: logger.getPrettyLogs(),
265
242
  };
266
243
  }
267
244
  } catch (e) {
@@ -270,7 +247,7 @@ export default async function createSandbox(QuickJS: QuickJSWASMModule, requireL
270
247
 
271
248
  return {
272
249
  success: false,
273
- logs: logger.logs,
250
+ logs: logger.getLogs(),
274
251
  };
275
252
  },
276
253
  };
package/src/utils.ts CHANGED
@@ -1,3 +1,33 @@
1
- export function delay(time):Promise<void> {
2
- return new Promise<void>(resolve => setTimeout(resolve, time));
3
- }
1
+ export function delay(time):Promise<void> {
2
+ return new Promise<void>(resolve => setTimeout(resolve, time));
3
+ }
4
+
5
+ const has = Object.prototype.hasOwnProperty;
6
+
7
+ export function dequal(foo: any, bar: any) {
8
+ let ctor, len;
9
+ if (foo === bar) return true;
10
+
11
+ if (foo && bar && (ctor=foo.constructor) === bar.constructor) {
12
+ if (ctor === Date) return foo.getTime() === bar.getTime();
13
+ if (ctor === RegExp) return foo.toString() === bar.toString();
14
+
15
+ if (ctor === Array) {
16
+ if ((len=foo.length) === bar.length) {
17
+ while (len-- && dequal(foo[len], bar[len]));
18
+ }
19
+ return len === -1;
20
+ }
21
+
22
+ if (!ctor || typeof foo === 'object') {
23
+ len = 0;
24
+ for (ctor in foo) {
25
+ if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
26
+ if (!(ctor in bar) || !dequal(foo[ctor], bar[ctor])) return false;
27
+ }
28
+ return Object.keys(bar).length === len;
29
+ }
30
+ }
31
+
32
+ return foo !== foo && bar !== bar;
33
+ }
package/tsconfig.json CHANGED
@@ -1,13 +1,13 @@
1
- {
2
- "compilerOptions": {
3
- "rootDir": "./src",
4
- "target": "ES2021" /* Node 16+ per https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping */,
5
- "module": "nodenext" /* Some imports are really imports: https://www.typescriptlang.org/docs/handbook/esm-node.html */,
6
- "moduleResolution": "nodenext" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
7
- "lib": ["ES2021", "dom"] /* Specify library files to be included in the compilation. */,
8
- "outDir": "./dist" /* Redirect output structure to the directory. */,
9
- "declaration": true
10
- },
11
- "include": ["**/src/*.ts"],
12
- "exclude": ["**/node_modules, **/dist"]
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": "./src",
4
+ "target": "ES2021" /* Node 16+ per https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping */,
5
+ "module": "nodenext" /* Some imports are really imports: https://www.typescriptlang.org/docs/handbook/esm-node.html */,
6
+ "moduleResolution": "nodenext" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
7
+ "lib": ["ES2021", "dom"] /* Specify library files to be included in the compilation. */,
8
+ "outDir": "./dist" /* Redirect output structure to the directory. */,
9
+ "declaration": true
10
+ },
11
+ "include": ["**/src/*.ts"],
12
+ "exclude": ["**/node_modules, **/dist"]
13
13
  }
@@ -1,37 +0,0 @@
1
-
2
- Most recent user query:
3
- {{USER_QUERY}}
4
-
5
- ---
6
-
7
- Based on the prior conversation, write a typescript script that performs the operation requested by the user and call the `submitCode` tool with the script.
8
-
9
- ## API documentation
10
-
11
- You can make use of this global API object:
12
-
13
- `api.ts`:
14
- ```typescript
15
- {{API}}
16
- ```
17
-
18
- ## Instructions
19
-
20
- Use the global api object to make calls to the API.
21
-
22
- You may use top level `await`.
23
-
24
- If needed, you may use `runCode` to run any non-destructive API calls to gather data for your script. Nothing will be visible to you unless you `console.log` it.
25
-
26
- You may use the `checkCode` tool to confirm that your code passes typescript compilation and doesn't have errors before submitting.
27
-
28
- 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 (errors can stay).
29
-
30
- When finished, you must call `submitCode` to submit the final version of the code, then respond with "Successfully submitted code" on success. On failure, correct any errors and submit again.
31
-
32
- ---
33
-
34
- {{DOCUMENTATION}}
35
-
36
- {{CONTEXT}}
37
-