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/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,19 +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;
145
+ } else if (value instanceof Date) {
146
+ const res = vm.evalCode(`new Date(${value.getTime()})`);
147
+ return isSuccess(res) ? res.value : null;
61
148
  } else if (typeof value === "object") {
62
- return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess);
149
+ return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess, logger);
63
150
  } else if (typeof value === "string") {
64
151
  return vm.newString(value);
65
152
  } else if (typeof value === "number") {
@@ -67,17 +154,19 @@ function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess) {
67
154
  } else if (typeof value === "bigint") {
68
155
  return vm.newBigInt(value);
69
156
  } else if (typeof value === "boolean") {
70
- return vm.evalCode(value ? "true" : "false").value;
157
+ const res = vm.evalCode(value ? "true" : "false");
158
+ return isSuccess(res) ? res.value : null;
71
159
  } else if (typeof value === "undefined") {
72
160
  return vm.undefined;
73
161
  } else {
162
+ console.error("Unknown type", value);
74
163
  return null;
75
164
  }
76
165
  }
77
- function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
166
+ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess, logger) {
78
167
  const vmObject = vm.newObject();
79
168
  for (const [key, value] of Object.entries(obj)) {
80
- let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
169
+ let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
81
170
  if (wrappedValue !== null) {
82
171
  vm.setProp(vmObject, key, wrappedValue);
83
172
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -87,11 +176,11 @@ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
87
176
  }
88
177
  return vmObject;
89
178
  }
90
- function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess) {
179
+ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess, logger) {
91
180
  const vmObject = vm.newObject();
92
181
  whitelist.forEach((key) => {
93
182
  const value = obj[key];
94
- const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
183
+ const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
95
184
  if (wrappedValue !== null) {
96
185
  vm.setProp(vmObject, key, wrappedValue);
97
186
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -101,10 +190,10 @@ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProc
101
190
  });
102
191
  return vmObject;
103
192
  }
104
- function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
193
+ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess, logger) {
105
194
  const vmArray = vm.newArray();
106
195
  for (let i = 0; i < arr.length; i++) {
107
- let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess);
196
+ let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess, logger);
108
197
  vm.setProp(vmArray, i, wrappedValue);
109
198
  if (wrappedValue != vm.undefined && wrappedValue != vm.null) {
110
199
  wrappedValue.dispose();
@@ -112,15 +201,47 @@ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
112
201
  }
113
202
  return vmArray;
114
203
  }
115
- 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) {
116
217
  const vmFn = vm.newFunction(fn.name, (...args) => {
117
218
  const unwrappedArgs = args.map(vm.dump);
118
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
+ }
119
235
  const result = fn.call(context, ...unwrappedArgs);
120
- 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);
121
238
  return wrappedResult;
122
239
  } catch (e) {
123
- 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);
124
245
  }
125
246
  });
126
247
  return vmFn;
@@ -208,34 +329,6 @@ function tsCompile(source, options) {
208
329
  }
209
330
  return ts.transpileModule(source, options).outputText;
210
331
  }
211
- class Logger {
212
- constructor(debug = false) {
213
- this.logs = [];
214
- this.debug = false;
215
- this.debug = debug;
216
- }
217
- log(args, source) {
218
- if (Array.isArray(args)) {
219
- this.logs.push({ type: "log", args, source });
220
- } else {
221
- this.logs.push({ type: "log", args: [args], source });
222
- }
223
- if (this.debug) {
224
- console.log(`[${source}]:`, ...args);
225
- }
226
- }
227
- error(args, source) {
228
- if (Array.isArray(args)) {
229
- this.logs.push({ type: "error", args, source });
230
- } else {
231
- this.logs.push({ type: "error", args: [args], source });
232
- }
233
- console.error(`[${source}]:`, ...args);
234
- }
235
- clear() {
236
- this.logs = [];
237
- }
238
- }
239
332
  async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug = false) {
240
333
  const vm = QuickJS.newContext();
241
334
  let errorState = false;
@@ -277,8 +370,9 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
277
370
  globalOption.value,
278
371
  globalOption.whitelist,
279
372
  beginAsyncProcess,
280
- endAsyncProcess
281
- ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess);
373
+ endAsyncProcess,
374
+ logger
375
+ ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess, logger);
282
376
  vm.setProp(vm.global, globalNames[i], globalObj);
283
377
  globalObj.dispose();
284
378
  }
@@ -286,7 +380,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
286
380
  const requireHandle = vm.newFunction("require", (...args) => {
287
381
  const nativeArgs = args.map(vm.dump);
288
382
  if (requireLookup[nativeArgs[0]]) {
289
- const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess);
383
+ const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess, logger);
290
384
  return returnObj;
291
385
  } else {
292
386
  return vm.undefined;
@@ -317,22 +411,22 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
317
411
  logger.error(["Could not compile:", code], "compiler");
318
412
  return {
319
413
  success: false,
320
- logs: logger.logs
414
+ logs: logger.getLogs()
321
415
  };
322
416
  }
323
417
  } catch (e) {
324
418
  logger.error(["Error testing code:", e], "compiler");
325
419
  return {
326
420
  success: false,
327
- logs: logger.logs
421
+ logs: logger.getLogs()
328
422
  };
329
423
  }
330
424
  return {
331
425
  success: true,
332
- logs: logger.logs
426
+ logs: logger.getLogs()
333
427
  };
334
428
  },
335
- runCode: (code) => {
429
+ runCode: async (code) => {
336
430
  try {
337
431
  logger.clear();
338
432
  const compiled = tsCompile(code);
@@ -340,7 +434,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
340
434
  logger.error(["Could not compile:", code], "compiler");
341
435
  return {
342
436
  success: false,
343
- logs: logger.logs
437
+ logs: logger.getLogs()
344
438
  };
345
439
  }
346
440
  errorState = false;
@@ -351,23 +445,37 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
351
445
  result.error.dispose();
352
446
  return {
353
447
  success: false,
354
- logs: logger.logs
448
+ logs: logger.getPrettyLogs()
355
449
  };
356
450
  } else if ("value" in result) {
451
+ const settled = vm.resolvePromise(result.value);
357
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();
358
466
  if (errorState) {
359
467
  const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
360
468
  logger.error(["An error was reported during execution. Compiled code with line numbers:\n", lines.join("\n")], "runner");
361
469
  }
362
470
  return {
363
471
  success: !errorState,
364
- logs: logger.logs
472
+ logs: logger.getPrettyLogs()
365
473
  };
366
474
  } else {
367
475
  logger.error(["Unknown execution result:", result], "runner");
368
476
  return {
369
477
  success: false,
370
- logs: logger.logs
478
+ logs: logger.getPrettyLogs()
371
479
  };
372
480
  }
373
481
  } catch (e) {
@@ -375,7 +483,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
375
483
  }
376
484
  return {
377
485
  success: false,
378
- logs: logger.logs
486
+ logs: logger.getLogs()
379
487
  };
380
488
  }
381
489
  };
@@ -384,13 +492,12 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
384
492
  require$1("dotenv").config();
385
493
  const openai = new OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
386
494
  let QuickJS = null;
495
+ function createLog(message, source) {
496
+ return { type: "log", args: [message], source };
497
+ }
387
498
  const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
388
499
  (async () => {
389
- try {
390
- ${code}
391
- } catch(err) {
392
- console.error(err);
393
- }
500
+ ${code}
394
501
  })();
395
502
  `;
396
503
  const wrapCodeBlock = (code, codeType = "") => `
@@ -404,13 +511,13 @@ function zodParseJSON(schema) {
404
511
  function createBasePrompt(apiFilePath, apiGlobalName, documentationPath) {
405
512
  const apiText = fs.readFileSync(apiFilePath, "utf8");
406
513
  const documentationText = documentationPath ? fs.readFileSync(documentationPath, "utf8") : "";
407
- 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 || "");
408
515
  return createTaskPrompt;
409
516
  }
410
517
  const runCodeSchema = z.object({
411
518
  code: z.string()
412
519
  });
413
- const checkCodeSchema = z.object({
520
+ z.object({
414
521
  code: z.string()
415
522
  });
416
523
  const submitCodeSchema = z.object({
@@ -432,34 +539,42 @@ const generateCode = async function(instance, queryText, userChatHistory, create
432
539
  if (debug) {
433
540
  console.log("Running code...", code);
434
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
+ }
435
550
  const res = await instance.runCode(code);
436
551
  if (hideLogsFromAgent) {
437
552
  res.logs = [];
438
553
  }
439
554
  return res;
440
555
  },
441
- 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.",
442
557
  parse: zodParseJSON(runCodeSchema),
443
- parameters: zodToJsonSchema(runCodeSchema)
444
- }
445
- },
446
- {
447
- type: "function",
448
- function: {
449
- name: "checkCode",
450
- // @ts-ignore
451
- function: async ({ code }) => {
452
- if (debug) {
453
- console.log("Checking code...", code);
454
- }
455
- const res = await instance.checkCode(code);
456
- return res;
457
- },
458
- description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
459
- parse: zodParseJSON(checkCodeSchema),
460
- parameters: zodToJsonSchema(checkCodeSchema)
558
+ parameters: runCodeSchema.toJSONSchema()
461
559
  }
462
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
+ // },
463
578
  {
464
579
  type: "function",
465
580
  function: {
@@ -474,14 +589,18 @@ const generateCode = async function(instance, queryText, userChatHistory, create
474
589
  logs: checkRes.logs
475
590
  };
476
591
  }
477
- finalSubmittedCode = code;
478
- return {
479
- success: true
480
- };
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;
481
600
  },
482
- 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.",
483
602
  parse: zodParseJSON(submitCodeSchema),
484
- parameters: zodToJsonSchema(submitCodeSchema)
603
+ parameters: submitCodeSchema.toJSONSchema()
485
604
  }
486
605
  }
487
606
  ];
@@ -503,17 +622,13 @@ const generateCode = async function(instance, queryText, userChatHistory, create
503
622
  ...additionalModelOptions
504
623
  }).on("message", async (message) => {
505
624
  if (debug) {
506
- console.log("Message:", JSON.stringify(message, null, 2));
625
+ if ("reasoning_content" in message) {
626
+ console.log(message.reasoning_content);
627
+ }
507
628
  }
508
629
  newHistoryItems.push(message);
509
630
  }).on("functionToolCall", (functionCall) => {
510
- if (debug) {
511
- console.log("Function Call:", JSON.stringify(functionCall, null, 2));
512
- }
513
631
  }).on("functionToolCallResult", (functionCall) => {
514
- if (debug) {
515
- console.log("Function Call Result:", JSON.stringify(functionCall, null, 2));
516
- }
517
632
  });
518
633
  const finalContent = await runner.finalContent();
519
634
  if (debug) {
@@ -617,7 +732,7 @@ async function createWithAPI(options) {
617
732
  console.error("Unknown failure checking code");
618
733
  return {
619
734
  success: false,
620
- logs: []
735
+ logs: [createLog("Unknown failure checking code", "compiler")]
621
736
  };
622
737
  }
623
738
  if (debug) {
@@ -658,7 +773,7 @@ async function createWithAPI(options) {
658
773
  };
659
774
  }
660
775
  }
661
- const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
776
+ const { vm, runCode: sandbox_runCode, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
662
777
  [apiDefFilePath]: apiExports
663
778
  } : void 0, {
664
779
  ...apiGlobals,
@@ -671,7 +786,7 @@ async function createWithAPI(options) {
671
786
  if (debug) {
672
787
  console.log("Running Code:\n", code);
673
788
  }
674
- const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
789
+ const res = await sandbox_runCode(wrapCode(apiGlobalName, apiDefFilePath, code));
675
790
  if (!res) {
676
791
  console.error("Unknown failure running task");
677
792
  return {
@@ -702,27 +817,35 @@ async function createWithAPI(options) {
702
817
  // generates code and runs it in one step
703
818
  processRequest: async function(userQuery, currentContext = void 0) {
704
819
  if (debug) {
705
- console.log("Query:", userQuery);
820
+ console.log("[debug] Query:", userQuery);
706
821
  }
707
822
  console.time("Generate Task");
823
+ const prompt = createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : "");
708
824
  const generatedCode = await generateCode(
709
825
  instance,
710
826
  userQuery,
711
827
  [],
712
- createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : ""),
828
+ prompt,
713
829
  debug,
714
830
  hideLogsFromAgent,
715
831
  model,
716
832
  additionalModelOptions
717
833
  );
718
834
  console.timeEnd("Generate Task");
719
- 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");
720
840
  if (generatedCode?.code) {
721
- 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
+ }
722
845
  } else {
723
846
  console.error("No code generated", generatedCode);
724
847
  }
725
- console.timeEnd("Run Code");
848
+ console.timeEnd("Run Code took");
726
849
  return generatedCode;
727
850
  }
728
851
  };
@@ -1,31 +1,42 @@
1
- import { AIMyAPI } from "../src";
2
- import { API } from "./sales_api_impl";
3
-
4
- // Simpler example using no support for chat history;
5
-
6
- (async () => {
7
- const api = new API();
8
-
9
- const aimyapi = await AIMyAPI.createWithAPI({
10
- apiObject: api,
11
- apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
12
- apiDefFilePath: "./example/sales_api.ts",
13
- apiDocsPath: "./example/sales_api.md",
14
- debug: false,
15
- })
16
-
17
- aimyapi.runCode(`console.log("Hello from the sandbox! Here is some sales data:", salesApi.getSalesData())`);
18
-
19
- console.log("Print 'hello' three times.")
20
- await aimyapi.processRequest("Print 'hello' three times.");
21
-
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");
24
-
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
-
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");
1
+ import { AIMyAPI } from "../src";
2
+ import { API } from "./sales_api_impl";
3
+
4
+ // Simpler example using no support for chat history;
5
+
6
+ (async () => {
7
+ const api = new API();
8
+
9
+ const aimyapi = await AIMyAPI.createWithAPI({
10
+ apiObject: api,
11
+ apiGlobalName: "salesApi", // Should match whatever you declared as your global in your api.
12
+ apiDefFilePath: "./example/sales_api.ts",
13
+ apiDocsPath: "./example/sales_api.md",
14
+ debug: false,
15
+ })
16
+
17
+ // test the sandbox:
18
+ await aimyapi.runCode(`await salesApi.display("Hello from the sandbox! Here is some sales data:");`);
19
+
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");`);
25
+
26
+ await aimyapi.runCode(`await salesApi.display(salesApi.getDate());`);
27
+
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
+ }
41
+
31
42
  })();