aimyapi 1.0.9 → 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/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { createRequire } from 'module';
2
2
  import fs from 'fs';
3
3
  import { OpenAI } from 'openai';
4
- import { getQuickJS } from 'quickjs-emscripten';
4
+ import { isSuccess, getQuickJS } from 'quickjs-emscripten';
5
5
  import * as ts from 'typescript';
6
- import { z } from 'zod';
7
- import { zodToJsonSchema } from 'zod-to-json-schema';
6
+ import { ZodError, z } from 'zod';
7
+ import path from 'path';
8
8
 
9
9
  var require$1 = (
10
10
  true
@@ -12,23 +12,104 @@ var require$1 = (
12
12
  : require
13
13
  );
14
14
 
15
+ class Logger {
16
+ constructor(debug = false) {
17
+ this.logs = [];
18
+ this.debug = false;
19
+ this.debug = debug;
20
+ }
21
+ getLogs() {
22
+ return this.logs;
23
+ }
24
+ addEntry(type, args, source) {
25
+ if (Array.isArray(args)) {
26
+ this.logs.push({ type, args, source });
27
+ } else {
28
+ this.logs.push({ type, args: [args], source });
29
+ }
30
+ }
31
+ log(args, source) {
32
+ this.addEntry("log", args, source);
33
+ if (this.debug) {
34
+ console.log(`[${source}]:`, ...args);
35
+ }
36
+ }
37
+ trace(fnName, fnArgs, result) {
38
+ this.logs.push({ type: "trace", fnName, fnArgs, result });
39
+ if (this.debug) {
40
+ console.debug(`[sandbox]: ${fnName}(${fnArgs.map((arg) => JSON.stringify(Logger.limitObjectForLogs(arg))).join(",")}) -> ${JSON.stringify(Logger.limitObjectForLogs(result))}`);
41
+ }
42
+ }
43
+ error(args, source) {
44
+ this.addEntry("error", args, source);
45
+ if (this.debug) {
46
+ console.error(`[${source}]:`, ...args);
47
+ }
48
+ }
49
+ clear() {
50
+ this.logs = [];
51
+ }
52
+ getPrettyLogs() {
53
+ return this.logs.map((entry) => Logger.limitObjectForLogs(entry));
54
+ }
55
+ /**
56
+ * Returns a trimmed copy of `value` that is safe to log.
57
+ * - Objects/arrays nested deeper than `maxDepth` become "[Object]" / "[Array(n)]".
58
+ * - Arrays longer than `maxArrayItems` keep the first items plus a "+N more items" string.
59
+ * - Circular references become "[Circular]".
60
+ */
61
+ static limitObjectForLogs(value, maxDepth = 3, maxArrayItems = 5) {
62
+ const seen = /* @__PURE__ */ new WeakSet();
63
+ const trim = (val, depth) => {
64
+ if (val === null || typeof val !== "object") {
65
+ if (typeof val === "function") return `[Function${val.name ? `: ${val.name}` : ""}]`;
66
+ if (typeof val === "bigint") return `${val}n`;
67
+ if (typeof val === "symbol") return val.toString();
68
+ return val;
69
+ }
70
+ if (val instanceof Date) return val.toISOString();
71
+ if (val instanceof Error) {
72
+ return { name: val.name, message: val.message, stack: val.stack };
73
+ }
74
+ if (seen.has(val)) return "[Circular]";
75
+ if (depth >= maxDepth) {
76
+ return Array.isArray(val) ? `[Array(${val.length})]` : "[Object]";
77
+ }
78
+ seen.add(val);
79
+ let result;
80
+ if (Array.isArray(val)) {
81
+ result = val.slice(0, maxArrayItems).map((item) => trim(item, depth + 1));
82
+ if (val.length > maxArrayItems) {
83
+ result.push(`+${val.length - maxArrayItems} more items`);
84
+ }
85
+ } else {
86
+ result = {};
87
+ for (const key of Object.keys(val)) {
88
+ result[key] = trim(val[key], depth + 1);
89
+ }
90
+ }
91
+ seen.delete(val);
92
+ return result;
93
+ };
94
+ return trim(value, 0);
95
+ }
96
+ }
97
+
15
98
  let promiseId = 0;
16
99
  let openPromises = {};
17
- function wrapPromise(vm, promise, beginAsyncProcess, endAsyncProcess) {
100
+ function wrapPromise(vm, promise, beginAsyncProcess, endAsyncProcess, logger) {
18
101
  promiseId += 1;
19
102
  const vmPromise = vm.newPromise();
20
103
  vmPromise._promiseId = promiseId;
21
104
  beginAsyncProcess();
22
105
  promise.then((...args) => {
23
106
  endAsyncProcess();
24
- const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess));
107
+ const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess, logger));
25
108
  openPromises[vmPromise._promiseId] = null;
26
109
  vmPromise.resolve(...wrappedArgs);
27
110
  wrappedArgs.forEach((arg) => arg.dispose());
28
- }).catch((...args) => {
29
- const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess));
30
- vmPromise.reject(...wrappedArgs);
31
- wrappedArgs.forEach((arg) => arg.dispose());
111
+ }).catch((error) => {
112
+ vmPromise.reject(vm.newError(error?.message || "An error occurred"));
32
113
  openPromises[vmPromise._promiseId] = null;
33
114
  });
34
115
  vmPromise.settled.then(() => {
@@ -47,21 +128,25 @@ function rejectOpenPromises(vm) {
47
128
  }
48
129
  vm.runtime.executePendingJobs();
49
130
  }
50
- function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess) {
131
+ const isPromise = (value) => {
132
+ return typeof value === "object" && typeof value.then === "function";
133
+ };
134
+ function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess, logger) {
51
135
  if (value === null) {
52
136
  return null;
53
- } else if (typeof value === "object" && typeof value.then === "function") {
54
- return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess);
137
+ } else if (isPromise(value)) {
138
+ return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess, logger);
55
139
  } else if (typeof value === "function") {
56
- return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess);
140
+ return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess, logger);
57
141
  } else if (Array.isArray(value)) {
58
- return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess);
142
+ return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess, logger);
59
143
  } else if (value === null) {
60
144
  return vm.null;
61
145
  } else if (value instanceof Date) {
62
- return vm.evalCode(`new Date(${value.getTime()})`).value;
146
+ const res = vm.evalCode(`new Date(${value.getTime()})`);
147
+ return isSuccess(res) ? res.value : null;
63
148
  } else if (typeof value === "object") {
64
- return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess);
149
+ return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess, logger);
65
150
  } else if (typeof value === "string") {
66
151
  return vm.newString(value);
67
152
  } else if (typeof value === "number") {
@@ -69,17 +154,19 @@ function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess) {
69
154
  } else if (typeof value === "bigint") {
70
155
  return vm.newBigInt(value);
71
156
  } else if (typeof value === "boolean") {
72
- return vm.evalCode(value ? "true" : "false").value;
157
+ const res = vm.evalCode(value ? "true" : "false");
158
+ return isSuccess(res) ? res.value : null;
73
159
  } else if (typeof value === "undefined") {
74
160
  return vm.undefined;
75
161
  } else {
162
+ console.error("Unknown type", value);
76
163
  return null;
77
164
  }
78
165
  }
79
- function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
166
+ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess, logger) {
80
167
  const vmObject = vm.newObject();
81
168
  for (const [key, value] of Object.entries(obj)) {
82
- let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
169
+ let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
83
170
  if (wrappedValue !== null) {
84
171
  vm.setProp(vmObject, key, wrappedValue);
85
172
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -89,11 +176,11 @@ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
89
176
  }
90
177
  return vmObject;
91
178
  }
92
- function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess) {
179
+ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess, logger) {
93
180
  const vmObject = vm.newObject();
94
181
  whitelist.forEach((key) => {
95
182
  const value = obj[key];
96
- const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
183
+ const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
97
184
  if (wrappedValue !== null) {
98
185
  vm.setProp(vmObject, key, wrappedValue);
99
186
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -103,10 +190,10 @@ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProc
103
190
  });
104
191
  return vmObject;
105
192
  }
106
- function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
193
+ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess, logger) {
107
194
  const vmArray = vm.newArray();
108
195
  for (let i = 0; i < arr.length; i++) {
109
- let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess);
196
+ let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess, logger);
110
197
  vm.setProp(vmArray, i, wrappedValue);
111
198
  if (wrappedValue != vm.undefined && wrappedValue != vm.null) {
112
199
  wrappedValue.dispose();
@@ -114,15 +201,47 @@ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
114
201
  }
115
202
  return vmArray;
116
203
  }
117
- function wrapGenericFunction(vm, fn, context = void 0, beginAsyncProcess, endAsyncProcess) {
204
+ function validationDecorator(schema) {
205
+ return function(...args) {
206
+ let argumentObject = {};
207
+ const params = Object.keys(schema.def.shape);
208
+ args.forEach((value, index) => {
209
+ if (index < params.length) {
210
+ argumentObject[params[index]] = value;
211
+ }
212
+ });
213
+ schema.parse(argumentObject);
214
+ };
215
+ }
216
+ function wrapGenericFunction(vm, fn, context = void 0, beginAsyncProcess, endAsyncProcess, logger) {
118
217
  const vmFn = vm.newFunction(fn.name, (...args) => {
119
218
  const unwrappedArgs = args.map(vm.dump);
120
219
  try {
220
+ const validatorName = `_params_${fn.name}`;
221
+ const hasValidator = context != void 0 && validatorName in context && "parse" in context[validatorName];
222
+ if (hasValidator) {
223
+ const schema = context[validatorName];
224
+ try {
225
+ const validator = validationDecorator(schema);
226
+ validator(...unwrappedArgs);
227
+ } catch (e) {
228
+ if (e instanceof ZodError) {
229
+ throw new Error(`Parameter validation failed for function "${fn.name}". Expected Parameters: [${Object.keys(schema.def.shape).join(",")}]. Errors:
230
+ ${z.prettifyError(e)}`);
231
+ }
232
+ throw new Error(`Parameter validation error calling ${fn.name}`);
233
+ }
234
+ }
121
235
  const result = fn.call(context, ...unwrappedArgs);
122
- const wrappedResult = wrap(vm, result, void 0, beginAsyncProcess, endAsyncProcess);
236
+ logger.trace(fn.name, unwrappedArgs, result);
237
+ const wrappedResult = wrap(vm, result, void 0, beginAsyncProcess, endAsyncProcess, logger);
123
238
  return wrappedResult;
124
239
  } catch (e) {
125
- console.log("Error", e);
240
+ logger.error([e], "sandbox");
241
+ if (e instanceof Error) {
242
+ throw e;
243
+ }
244
+ throw new Error("An exception occurred calling " + fn.name);
126
245
  }
127
246
  });
128
247
  return vmFn;
@@ -210,34 +329,6 @@ function tsCompile(source, options) {
210
329
  }
211
330
  return ts.transpileModule(source, options).outputText;
212
331
  }
213
- class Logger {
214
- constructor(debug = false) {
215
- this.logs = [];
216
- this.debug = false;
217
- this.debug = debug;
218
- }
219
- log(args, source) {
220
- if (Array.isArray(args)) {
221
- this.logs.push({ type: "log", args, source });
222
- } else {
223
- this.logs.push({ type: "log", args: [args], source });
224
- }
225
- if (this.debug) {
226
- console.log(`[${source}]:`, ...args);
227
- }
228
- }
229
- error(args, source) {
230
- if (Array.isArray(args)) {
231
- this.logs.push({ type: "error", args, source });
232
- } else {
233
- this.logs.push({ type: "error", args: [args], source });
234
- }
235
- console.error(`[${source}]:`, ...args);
236
- }
237
- clear() {
238
- this.logs = [];
239
- }
240
- }
241
332
  async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug = false) {
242
333
  const vm = QuickJS.newContext();
243
334
  let errorState = false;
@@ -279,8 +370,9 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
279
370
  globalOption.value,
280
371
  globalOption.whitelist,
281
372
  beginAsyncProcess,
282
- endAsyncProcess
283
- ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess);
373
+ endAsyncProcess,
374
+ logger
375
+ ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess, logger);
284
376
  vm.setProp(vm.global, globalNames[i], globalObj);
285
377
  globalObj.dispose();
286
378
  }
@@ -288,7 +380,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
288
380
  const requireHandle = vm.newFunction("require", (...args) => {
289
381
  const nativeArgs = args.map(vm.dump);
290
382
  if (requireLookup[nativeArgs[0]]) {
291
- const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess);
383
+ const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess, logger);
292
384
  return returnObj;
293
385
  } else {
294
386
  return vm.undefined;
@@ -319,22 +411,22 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
319
411
  logger.error(["Could not compile:", code], "compiler");
320
412
  return {
321
413
  success: false,
322
- logs: logger.logs
414
+ logs: logger.getLogs()
323
415
  };
324
416
  }
325
417
  } catch (e) {
326
418
  logger.error(["Error testing code:", e], "compiler");
327
419
  return {
328
420
  success: false,
329
- logs: logger.logs
421
+ logs: logger.getLogs()
330
422
  };
331
423
  }
332
424
  return {
333
425
  success: true,
334
- logs: logger.logs
426
+ logs: logger.getLogs()
335
427
  };
336
428
  },
337
- runCode: (code) => {
429
+ runCode: async (code) => {
338
430
  try {
339
431
  logger.clear();
340
432
  const compiled = tsCompile(code);
@@ -342,7 +434,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
342
434
  logger.error(["Could not compile:", code], "compiler");
343
435
  return {
344
436
  success: false,
345
- logs: logger.logs
437
+ logs: logger.getLogs()
346
438
  };
347
439
  }
348
440
  errorState = false;
@@ -353,23 +445,37 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
353
445
  result.error.dispose();
354
446
  return {
355
447
  success: false,
356
- logs: logger.logs
448
+ logs: logger.getPrettyLogs()
357
449
  };
358
450
  } else if ("value" in result) {
451
+ const settled = vm.resolvePromise(result.value);
359
452
  result.value.dispose();
453
+ vm.runtime.executePendingJobs();
454
+ const promiseResult = await settled;
455
+ if (promiseResult.error) {
456
+ const err = vm.dump(promiseResult.error);
457
+ promiseResult.error.dispose();
458
+ const lines = compiled.split("\n").map((l, i) => `${i + 1}: ${l}`);
459
+ logger.error(["Uncaught exception:", err, "\n", lines.join("\n")], "runner");
460
+ return {
461
+ success: false,
462
+ logs: logger.getPrettyLogs()
463
+ };
464
+ }
465
+ promiseResult.value.dispose();
360
466
  if (errorState) {
361
467
  const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
362
468
  logger.error(["An error was reported during execution. Compiled code with line numbers:\n", lines.join("\n")], "runner");
363
469
  }
364
470
  return {
365
471
  success: !errorState,
366
- logs: logger.logs
472
+ logs: logger.getPrettyLogs()
367
473
  };
368
474
  } else {
369
475
  logger.error(["Unknown execution result:", result], "runner");
370
476
  return {
371
477
  success: false,
372
- logs: logger.logs
478
+ logs: logger.getPrettyLogs()
373
479
  };
374
480
  }
375
481
  } catch (e) {
@@ -377,7 +483,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
377
483
  }
378
484
  return {
379
485
  success: false,
380
- logs: logger.logs
486
+ logs: logger.getLogs()
381
487
  };
382
488
  }
383
489
  };
@@ -386,13 +492,12 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
386
492
  require$1("dotenv").config();
387
493
  const openai = new OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
388
494
  let QuickJS = null;
495
+ function createLog(message, source) {
496
+ return { type: "log", args: [message], source };
497
+ }
389
498
  const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
390
499
  (async () => {
391
- try {
392
- ${code}
393
- } catch(err) {
394
- console.error(err);
395
- }
500
+ ${code}
396
501
  })();
397
502
  `;
398
503
  const wrapCodeBlock = (code, codeType = "") => `
@@ -406,13 +511,13 @@ function zodParseJSON(schema) {
406
511
  function createBasePrompt(apiFilePath, apiGlobalName, documentationPath) {
407
512
  const apiText = fs.readFileSync(apiFilePath, "utf8");
408
513
  const documentationText = documentationPath ? fs.readFileSync(documentationPath, "utf8") : "";
409
- const createTaskPrompt = fs.readFileSync("./prompts/create-task-prompt.md", "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
514
+ const createTaskPrompt = fs.readFileSync(path.resolve(__dirname, "../prompts/generate-code-prompt.md"), "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
410
515
  return createTaskPrompt;
411
516
  }
412
517
  const runCodeSchema = z.object({
413
518
  code: z.string()
414
519
  });
415
- const checkCodeSchema = z.object({
520
+ z.object({
416
521
  code: z.string()
417
522
  });
418
523
  const submitCodeSchema = z.object({
@@ -434,34 +539,42 @@ const generateCode = async function(instance, queryText, userChatHistory, create
434
539
  if (debug) {
435
540
  console.log("Running code...", code);
436
541
  }
542
+ const checkRes = await instance.checkCode(code);
543
+ if (!checkRes.success) {
544
+ return {
545
+ success: false,
546
+ reason: "Code check failed",
547
+ logs: checkRes.logs
548
+ };
549
+ }
437
550
  const res = await instance.runCode(code);
438
551
  if (hideLogsFromAgent) {
439
552
  res.logs = [];
440
553
  }
441
554
  return res;
442
555
  },
443
- description: "Run the provided code in a sandboxed environment. The code will have access to the API object. Returns the result of the code execution.",
556
+ description: "Check and run the provided code in a sandboxed environment. The code will have access to the API object. Returns the result of the code execution. Use this for testing and experimentation.",
444
557
  parse: zodParseJSON(runCodeSchema),
445
- parameters: zodToJsonSchema(runCodeSchema)
446
- }
447
- },
448
- {
449
- type: "function",
450
- function: {
451
- name: "checkCode",
452
- // @ts-ignore
453
- function: async ({ code }) => {
454
- if (debug) {
455
- console.log("Checking code...", code);
456
- }
457
- const res = await instance.checkCode(code);
458
- return res;
459
- },
460
- description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
461
- parse: zodParseJSON(checkCodeSchema),
462
- parameters: zodToJsonSchema(checkCodeSchema)
558
+ parameters: runCodeSchema.toJSONSchema()
463
559
  }
464
560
  },
561
+ // {
562
+ // type: "function",
563
+ // function: {
564
+ // name: "checkCode",
565
+ // // @ts-ignore
566
+ // function: async ({code}: {code: string}) => {
567
+ // if(debug) {
568
+ // console.log("Checking code...", code);
569
+ // }
570
+ // const res = await instance.checkCode(code);
571
+ // return res;
572
+ // },
573
+ // description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
574
+ // parse: zodParseJSON(checkCodeSchema),
575
+ // parameters: checkCodeSchema.toJSONSchema(),
576
+ // }
577
+ // },
465
578
  {
466
579
  type: "function",
467
580
  function: {
@@ -476,14 +589,18 @@ const generateCode = async function(instance, queryText, userChatHistory, create
476
589
  logs: checkRes.logs
477
590
  };
478
591
  }
479
- finalSubmittedCode = code;
480
- return {
481
- success: true
482
- };
592
+ const res = await instance.runCode(code);
593
+ if (hideLogsFromAgent) {
594
+ res.logs = [];
595
+ }
596
+ if (res.success) {
597
+ finalSubmittedCode = code;
598
+ }
599
+ return res;
483
600
  },
484
- description: "Submit the provided code as the final code to run. This will end the code generation process and the code will be run in the sandbox. Use this when you are confident in the code you have generated and want to run it.",
601
+ description: "Submit the provided code as a candidate for the final code. The code will be checked and run and output logs and traces will be provided. Check the logs, if satisifed, respond to the user otherwise submit again.",
485
602
  parse: zodParseJSON(submitCodeSchema),
486
- parameters: zodToJsonSchema(submitCodeSchema)
603
+ parameters: submitCodeSchema.toJSONSchema()
487
604
  }
488
605
  }
489
606
  ];
@@ -505,17 +622,13 @@ const generateCode = async function(instance, queryText, userChatHistory, create
505
622
  ...additionalModelOptions
506
623
  }).on("message", async (message) => {
507
624
  if (debug) {
508
- console.log("Message:", JSON.stringify(message, null, 2));
625
+ if ("reasoning_content" in message) {
626
+ console.log(message.reasoning_content);
627
+ }
509
628
  }
510
629
  newHistoryItems.push(message);
511
630
  }).on("functionToolCall", (functionCall) => {
512
- if (debug) {
513
- console.log("Function Call:", JSON.stringify(functionCall, null, 2));
514
- }
515
631
  }).on("functionToolCallResult", (functionCall) => {
516
- if (debug) {
517
- console.log("Function Call Result:", JSON.stringify(functionCall, null, 2));
518
- }
519
632
  });
520
633
  const finalContent = await runner.finalContent();
521
634
  if (debug) {
@@ -619,7 +732,7 @@ async function createWithAPI(options) {
619
732
  console.error("Unknown failure checking code");
620
733
  return {
621
734
  success: false,
622
- logs: []
735
+ logs: [createLog("Unknown failure checking code", "compiler")]
623
736
  };
624
737
  }
625
738
  if (debug) {
@@ -660,7 +773,7 @@ async function createWithAPI(options) {
660
773
  };
661
774
  }
662
775
  }
663
- const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
776
+ const { vm, runCode: sandbox_runCode, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
664
777
  [apiDefFilePath]: apiExports
665
778
  } : void 0, {
666
779
  ...apiGlobals,
@@ -673,7 +786,7 @@ async function createWithAPI(options) {
673
786
  if (debug) {
674
787
  console.log("Running Code:\n", code);
675
788
  }
676
- const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
789
+ const res = await sandbox_runCode(wrapCode(apiGlobalName, apiDefFilePath, code));
677
790
  if (!res) {
678
791
  console.error("Unknown failure running task");
679
792
  return {
@@ -704,27 +817,35 @@ async function createWithAPI(options) {
704
817
  // generates code and runs it in one step
705
818
  processRequest: async function(userQuery, currentContext = void 0) {
706
819
  if (debug) {
707
- console.log("Query:", userQuery);
820
+ console.log("[debug] Query:", userQuery);
708
821
  }
709
822
  console.time("Generate Task");
823
+ const prompt = createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : "");
710
824
  const generatedCode = await generateCode(
711
825
  instance,
712
826
  userQuery,
713
827
  [],
714
- createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : ""),
828
+ prompt,
715
829
  debug,
716
830
  hideLogsFromAgent,
717
831
  model,
718
832
  additionalModelOptions
719
833
  );
720
834
  console.timeEnd("Generate Task");
721
- console.time("Run Code");
835
+ console.log(`generated code result
836
+ Success?: ${generatedCode?.success}
837
+ Comments: ${generatedCode?.comments}
838
+ Running Code...`);
839
+ console.time("Run Code took");
722
840
  if (generatedCode?.code) {
723
- await instance.runCode(generatedCode.code);
841
+ const codeRunResult = await instance.runCode(generatedCode.code);
842
+ if (!codeRunResult.success) {
843
+ console.error("Error running generated code");
844
+ }
724
845
  } else {
725
846
  console.error("No code generated", generatedCode);
726
847
  }
727
- console.timeEnd("Run Code");
848
+ console.timeEnd("Run Code took");
728
849
  return generatedCode;
729
850
  }
730
851
  };
@@ -14,18 +14,29 @@ import { API } from "./sales_api_impl";
14
14
  debug: false,
15
15
  })
16
16
 
17
- aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
17
+ // test the sandbox:
18
+ await aimyapi.runCode(`await salesApi.display("Hello from the sandbox! Here is some sales data:");`);
18
19
 
19
- console.log("Print 'hello' three times.")
20
- await aimyapi.processRequest("Print 'hello' three times.");
20
+ console.log("Test parameter validation (should fail)");
21
+ const failResult = await aimyapi.runCode(`await salesApi.sendEmail("fail");`);
22
+ console.log(JSON.stringify(failResult, null, 2));
23
+ console.log("Test parameter validation (should pass)");
24
+ await aimyapi.runCode(`await salesApi.sendEmail("to@email.com", "Your emails", "body text");`);
21
25
 
22
- console.log("What month had the highest sales in 2020 for any business unit?")
23
- await aimyapi.processRequest("What was our best month in 2020");
26
+ await aimyapi.runCode(`await salesApi.display(salesApi.getDate());`);
24
27
 
25
- console.log("Which business unit had the highest sales in 2020? Print the totals for each")
26
- await aimyapi.processRequest("Which business unit had the highest sales in 2020? Print the totals for each");
27
- // Note: this is a bit of a trick question because two of them are tied for first. The agent usually doesn't realize this edge case. Should we instruct it to look for edge cases?
28
+ // test code writing:
29
+ const queries = [ "Display 'hello' three times.", "What month had the highest sales in 2020 for any business unit?", "Which business unit had the highest sales in 2020? Display the totals for each business unit", "Compute the total sales for each month in 2020 then email the top 3 to test@email.com"]
30
+
31
+ for(const k in queries) {
32
+ const query = queries[k];
33
+ console.log(`Query: ${query}`);
34
+ const testResult = await aimyapi.processRequest(query);
35
+ if(testResult?.code)
36
+ console.log("Code:", testResult.code)
37
+ else {
38
+ console.log(testResult);
39
+ }
40
+ }
28
41
 
29
- console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
30
- await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
31
42
  })();
@@ -1,5 +1 @@
1
- ## Examples:
2
-
3
- to print hello:
4
-
5
- submitCode("salesApi.print(\"Hello\")");
1
+ Use the `salesApi` global to make your api calls against.
@@ -12,11 +12,13 @@ export interface APIInterface {
12
12
 
13
13
  sendEmail(to: string, subject: string, body: string): Promise<void>;
14
14
 
15
+ getDate(): Date;
16
+
15
17
  getSalesData(): SalesData[];
16
18
  // Returns an array of sales data.
17
19
 
18
- print(text: string): void;
19
- // Prints the specified text to the user.
20
+ display(text: string): void;
21
+ // display the specified text to the user. Always use this to respond with your result.
20
22
 
21
23
  delay(milliseconds: number): Promise<void>;
22
24
  // waits for the specified number of milliseconds before resolving the promise.