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/README.md CHANGED
@@ -114,7 +114,7 @@ for (let i = 0; i < salesData.length; i++) {
114
114
  businessUnitWithMaxSales = salesData[i].businessUnit;
115
115
  }
116
116
  }
117
- api.print(\`The business unit with the highest sales in 2020 was ${businessUnitWithMaxSales}.\`);
117
+ api.display(\`The business unit with the highest sales in 2020 was ${businessUnitWithMaxSales}.\`);
118
118
 
119
119
  ```
120
120
 
@@ -122,6 +122,31 @@ This example does not take advantage of the chat history and treats every reques
122
122
 
123
123
  APIs should be kept simple and understandable. If you have a complicated API you may want to write a simpler facade for it.
124
124
 
125
+ ### Limitations
126
+
127
+ The sandbox implementation supports basic types and the built in objects Promise and Date. It doesn't currently support Map, Set, Regex, etc. So you cannot return those types from your API functions. Some Date functionality differs from current javascript specs.
128
+
129
+ ### Recommendations
130
+
131
+ Create a separate sandbox with a mocked API for generating code. This way the agent doesn't modify anything while troubleshooting or running test scripts. Additionally it prevents the agent from ever seeing real data if you want to maintain privacy. Use the real API only when you want to run code.
132
+
133
+ Implement schema validation for your API functions. Follow the convention by defining `_params_[FUNCTIONNAME]` as a Zod object:
134
+
135
+ ```ts
136
+ // Schema validation for function parameters. Will throw if parameters are invalid to prevent silent failures and surface info to the agent.
137
+ // fields should be defined in the same order that they occur in the function
138
+ public _params_sendEmail = z.object({
139
+ to: z.string(),
140
+ subject: z.string(),
141
+ body: z.string().min(5)
142
+ })
143
+
144
+ // Mock implementation, doesn't actually send an email
145
+ async sendEmail(to: string, subject: string, body: string): Promise<void> {
146
+ ...
147
+ }
148
+ ```
149
+
125
150
 
126
151
  ## API Reference for AIMyAPI
127
152
 
@@ -175,11 +200,12 @@ export interface AIMyAPIInstance {
175
200
  - `generateCode()`: A function that generates code to be run in the sandbox for the given query text and user chat history.
176
201
  - `runCode()`: A function that runs the generated code in the sandbox.
177
202
  - `checkCode()`: Typecheck / compile the code
178
- - `processRequest()`: A single function that generates and runs code assuming no chat history.
203
+ - `processRequest()`: A single function that generates and runs code assuming no chat history. This is more of a convenience function for the examples, since code gen and runn
179
204
 
180
205
 
181
206
  ## Safety notes:
182
207
 
208
+ - When generating code, you should use a mocked version of your API. You can create separate sandboxes for writing code vs. running code.
183
209
  - If the user is giving sensitive information in a query, that information isn't private. Refer to the OpenAI policies and plan accordingly.
184
210
  - The LLM will do stupid things with your API. You should idiot proof your functions, make sure you sanity check any inputs, etc.
185
211
  - Even though we are running the code in sandbox, you should still treat anything coming back from the LLM as untrusted code.
package/dist/index.cjs CHANGED
@@ -6,7 +6,7 @@ var openai$1 = require('openai');
6
6
  var quickjsEmscripten = require('quickjs-emscripten');
7
7
  var ts = require('typescript');
8
8
  var zod = require('zod');
9
- var zodToJsonSchema = require('zod-to-json-schema');
9
+ var path = require('path');
10
10
 
11
11
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
12
12
  function _interopNamespaceDefault(e) {
@@ -34,23 +34,104 @@ var require$1 = (
34
34
  : require
35
35
  );
36
36
 
37
+ class Logger {
38
+ constructor(debug = false) {
39
+ this.logs = [];
40
+ this.debug = false;
41
+ this.debug = debug;
42
+ }
43
+ getLogs() {
44
+ return this.logs;
45
+ }
46
+ addEntry(type, args, source) {
47
+ if (Array.isArray(args)) {
48
+ this.logs.push({ type, args, source });
49
+ } else {
50
+ this.logs.push({ type, args: [args], source });
51
+ }
52
+ }
53
+ log(args, source) {
54
+ this.addEntry("log", args, source);
55
+ if (this.debug) {
56
+ console.log(`[${source}]:`, ...args);
57
+ }
58
+ }
59
+ trace(fnName, fnArgs, result) {
60
+ this.logs.push({ type: "trace", fnName, fnArgs, result });
61
+ if (this.debug) {
62
+ console.debug(`[sandbox]: ${fnName}(${fnArgs.map((arg) => JSON.stringify(Logger.limitObjectForLogs(arg))).join(",")}) -> ${JSON.stringify(Logger.limitObjectForLogs(result))}`);
63
+ }
64
+ }
65
+ error(args, source) {
66
+ this.addEntry("error", args, source);
67
+ if (this.debug) {
68
+ console.error(`[${source}]:`, ...args);
69
+ }
70
+ }
71
+ clear() {
72
+ this.logs = [];
73
+ }
74
+ getPrettyLogs() {
75
+ return this.logs.map((entry) => Logger.limitObjectForLogs(entry));
76
+ }
77
+ /**
78
+ * Returns a trimmed copy of `value` that is safe to log.
79
+ * - Objects/arrays nested deeper than `maxDepth` become "[Object]" / "[Array(n)]".
80
+ * - Arrays longer than `maxArrayItems` keep the first items plus a "+N more items" string.
81
+ * - Circular references become "[Circular]".
82
+ */
83
+ static limitObjectForLogs(value, maxDepth = 3, maxArrayItems = 5) {
84
+ const seen = /* @__PURE__ */ new WeakSet();
85
+ const trim = (val, depth) => {
86
+ if (val === null || typeof val !== "object") {
87
+ if (typeof val === "function") return `[Function${val.name ? `: ${val.name}` : ""}]`;
88
+ if (typeof val === "bigint") return `${val}n`;
89
+ if (typeof val === "symbol") return val.toString();
90
+ return val;
91
+ }
92
+ if (val instanceof Date) return val.toISOString();
93
+ if (val instanceof Error) {
94
+ return { name: val.name, message: val.message, stack: val.stack };
95
+ }
96
+ if (seen.has(val)) return "[Circular]";
97
+ if (depth >= maxDepth) {
98
+ return Array.isArray(val) ? `[Array(${val.length})]` : "[Object]";
99
+ }
100
+ seen.add(val);
101
+ let result;
102
+ if (Array.isArray(val)) {
103
+ result = val.slice(0, maxArrayItems).map((item) => trim(item, depth + 1));
104
+ if (val.length > maxArrayItems) {
105
+ result.push(`+${val.length - maxArrayItems} more items`);
106
+ }
107
+ } else {
108
+ result = {};
109
+ for (const key of Object.keys(val)) {
110
+ result[key] = trim(val[key], depth + 1);
111
+ }
112
+ }
113
+ seen.delete(val);
114
+ return result;
115
+ };
116
+ return trim(value, 0);
117
+ }
118
+ }
119
+
37
120
  let promiseId = 0;
38
121
  let openPromises = {};
39
- function wrapPromise(vm, promise, beginAsyncProcess, endAsyncProcess) {
122
+ function wrapPromise(vm, promise, beginAsyncProcess, endAsyncProcess, logger) {
40
123
  promiseId += 1;
41
124
  const vmPromise = vm.newPromise();
42
125
  vmPromise._promiseId = promiseId;
43
126
  beginAsyncProcess();
44
127
  promise.then((...args) => {
45
128
  endAsyncProcess();
46
- const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess));
129
+ const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess, logger));
47
130
  openPromises[vmPromise._promiseId] = null;
48
131
  vmPromise.resolve(...wrappedArgs);
49
132
  wrappedArgs.forEach((arg) => arg.dispose());
50
- }).catch((...args) => {
51
- const wrappedArgs = args.map((arg) => wrap(vm, arg, void 0, beginAsyncProcess, endAsyncProcess));
52
- vmPromise.reject(...wrappedArgs);
53
- wrappedArgs.forEach((arg) => arg.dispose());
133
+ }).catch((error) => {
134
+ vmPromise.reject(vm.newError(error?.message || "An error occurred"));
54
135
  openPromises[vmPromise._promiseId] = null;
55
136
  });
56
137
  vmPromise.settled.then(() => {
@@ -69,21 +150,25 @@ function rejectOpenPromises(vm) {
69
150
  }
70
151
  vm.runtime.executePendingJobs();
71
152
  }
72
- function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess) {
153
+ const isPromise = (value) => {
154
+ return typeof value === "object" && typeof value.then === "function";
155
+ };
156
+ function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess, logger) {
73
157
  if (value === null) {
74
158
  return null;
75
- } else if (typeof value === "object" && typeof value.then === "function") {
76
- return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess);
159
+ } else if (isPromise(value)) {
160
+ return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess, logger);
77
161
  } else if (typeof value === "function") {
78
- return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess);
162
+ return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess, logger);
79
163
  } else if (Array.isArray(value)) {
80
- return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess);
164
+ return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess, logger);
81
165
  } else if (value === null) {
82
166
  return vm.null;
83
167
  } else if (value instanceof Date) {
84
- return vm.evalCode(`new Date(${value.getTime()})`).value;
168
+ const res = vm.evalCode(`new Date(${value.getTime()})`);
169
+ return quickjsEmscripten.isSuccess(res) ? res.value : null;
85
170
  } else if (typeof value === "object") {
86
- return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess);
171
+ return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess, logger);
87
172
  } else if (typeof value === "string") {
88
173
  return vm.newString(value);
89
174
  } else if (typeof value === "number") {
@@ -91,17 +176,19 @@ function wrap(vm, value, context, beginAsyncProcess, endAsyncProcess) {
91
176
  } else if (typeof value === "bigint") {
92
177
  return vm.newBigInt(value);
93
178
  } else if (typeof value === "boolean") {
94
- return vm.evalCode(value ? "true" : "false").value;
179
+ const res = vm.evalCode(value ? "true" : "false");
180
+ return quickjsEmscripten.isSuccess(res) ? res.value : null;
95
181
  } else if (typeof value === "undefined") {
96
182
  return vm.undefined;
97
183
  } else {
184
+ console.error("Unknown type", value);
98
185
  return null;
99
186
  }
100
187
  }
101
- function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
188
+ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess, logger) {
102
189
  const vmObject = vm.newObject();
103
190
  for (const [key, value] of Object.entries(obj)) {
104
- let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
191
+ let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
105
192
  if (wrappedValue !== null) {
106
193
  vm.setProp(vmObject, key, wrappedValue);
107
194
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -111,11 +198,11 @@ function wrapObject(vm, obj, beginAsyncProcess, endAsyncProcess) {
111
198
  }
112
199
  return vmObject;
113
200
  }
114
- function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess) {
201
+ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProcess, logger) {
115
202
  const vmObject = vm.newObject();
116
203
  whitelist.forEach((key) => {
117
204
  const value = obj[key];
118
- const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess);
205
+ const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
119
206
  if (wrappedValue !== null) {
120
207
  vm.setProp(vmObject, key, wrappedValue);
121
208
  if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
@@ -125,10 +212,10 @@ function wrapObjectWhitelist(vm, obj, whitelist, beginAsyncProcess, endAsyncProc
125
212
  });
126
213
  return vmObject;
127
214
  }
128
- function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
215
+ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess, logger) {
129
216
  const vmArray = vm.newArray();
130
217
  for (let i = 0; i < arr.length; i++) {
131
- let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess);
218
+ let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess, logger);
132
219
  vm.setProp(vmArray, i, wrappedValue);
133
220
  if (wrappedValue != vm.undefined && wrappedValue != vm.null) {
134
221
  wrappedValue.dispose();
@@ -136,15 +223,47 @@ function wrapArray(vm, arr, beginAsyncProcess, endAsyncProcess) {
136
223
  }
137
224
  return vmArray;
138
225
  }
139
- function wrapGenericFunction(vm, fn, context = void 0, beginAsyncProcess, endAsyncProcess) {
226
+ function validationDecorator(schema) {
227
+ return function(...args) {
228
+ let argumentObject = {};
229
+ const params = Object.keys(schema.def.shape);
230
+ args.forEach((value, index) => {
231
+ if (index < params.length) {
232
+ argumentObject[params[index]] = value;
233
+ }
234
+ });
235
+ schema.parse(argumentObject);
236
+ };
237
+ }
238
+ function wrapGenericFunction(vm, fn, context = void 0, beginAsyncProcess, endAsyncProcess, logger) {
140
239
  const vmFn = vm.newFunction(fn.name, (...args) => {
141
240
  const unwrappedArgs = args.map(vm.dump);
142
241
  try {
242
+ const validatorName = `_params_${fn.name}`;
243
+ const hasValidator = context != void 0 && validatorName in context && "parse" in context[validatorName];
244
+ if (hasValidator) {
245
+ const schema = context[validatorName];
246
+ try {
247
+ const validator = validationDecorator(schema);
248
+ validator(...unwrappedArgs);
249
+ } catch (e) {
250
+ if (e instanceof zod.ZodError) {
251
+ throw new Error(`Parameter validation failed for function "${fn.name}". Expected Parameters: [${Object.keys(schema.def.shape).join(",")}]. Errors:
252
+ ${zod.z.prettifyError(e)}`);
253
+ }
254
+ throw new Error(`Parameter validation error calling ${fn.name}`);
255
+ }
256
+ }
143
257
  const result = fn.call(context, ...unwrappedArgs);
144
- const wrappedResult = wrap(vm, result, void 0, beginAsyncProcess, endAsyncProcess);
258
+ logger.trace(fn.name, unwrappedArgs, result);
259
+ const wrappedResult = wrap(vm, result, void 0, beginAsyncProcess, endAsyncProcess, logger);
145
260
  return wrappedResult;
146
261
  } catch (e) {
147
- console.log("Error", e);
262
+ logger.error([e], "sandbox");
263
+ if (e instanceof Error) {
264
+ throw e;
265
+ }
266
+ throw new Error("An exception occurred calling " + fn.name);
148
267
  }
149
268
  });
150
269
  return vmFn;
@@ -232,34 +351,6 @@ function tsCompile(source, options) {
232
351
  }
233
352
  return ts__namespace.transpileModule(source, options).outputText;
234
353
  }
235
- class Logger {
236
- constructor(debug = false) {
237
- this.logs = [];
238
- this.debug = false;
239
- this.debug = debug;
240
- }
241
- log(args, source) {
242
- if (Array.isArray(args)) {
243
- this.logs.push({ type: "log", args, source });
244
- } else {
245
- this.logs.push({ type: "log", args: [args], source });
246
- }
247
- if (this.debug) {
248
- console.log(`[${source}]:`, ...args);
249
- }
250
- }
251
- error(args, source) {
252
- if (Array.isArray(args)) {
253
- this.logs.push({ type: "error", args, source });
254
- } else {
255
- this.logs.push({ type: "error", args: [args], source });
256
- }
257
- console.error(`[${source}]:`, ...args);
258
- }
259
- clear() {
260
- this.logs = [];
261
- }
262
- }
263
354
  async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug = false) {
264
355
  const vm = QuickJS.newContext();
265
356
  let errorState = false;
@@ -301,8 +392,9 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
301
392
  globalOption.value,
302
393
  globalOption.whitelist,
303
394
  beginAsyncProcess,
304
- endAsyncProcess
305
- ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess);
395
+ endAsyncProcess,
396
+ logger
397
+ ) : wrap(vm, globalOption.value, globalOption, beginAsyncProcess, endAsyncProcess, logger);
306
398
  vm.setProp(vm.global, globalNames[i], globalObj);
307
399
  globalObj.dispose();
308
400
  }
@@ -310,7 +402,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
310
402
  const requireHandle = vm.newFunction("require", (...args) => {
311
403
  const nativeArgs = args.map(vm.dump);
312
404
  if (requireLookup[nativeArgs[0]]) {
313
- const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess);
405
+ const returnObj = wrapObject(vm, requireLookup[nativeArgs[0]], beginAsyncProcess, endAsyncProcess, logger);
314
406
  return returnObj;
315
407
  } else {
316
408
  return vm.undefined;
@@ -341,22 +433,22 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
341
433
  logger.error(["Could not compile:", code], "compiler");
342
434
  return {
343
435
  success: false,
344
- logs: logger.logs
436
+ logs: logger.getLogs()
345
437
  };
346
438
  }
347
439
  } catch (e) {
348
440
  logger.error(["Error testing code:", e], "compiler");
349
441
  return {
350
442
  success: false,
351
- logs: logger.logs
443
+ logs: logger.getLogs()
352
444
  };
353
445
  }
354
446
  return {
355
447
  success: true,
356
- logs: logger.logs
448
+ logs: logger.getLogs()
357
449
  };
358
450
  },
359
- runCode: (code) => {
451
+ runCode: async (code) => {
360
452
  try {
361
453
  logger.clear();
362
454
  const compiled = tsCompile(code);
@@ -364,7 +456,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
364
456
  logger.error(["Could not compile:", code], "compiler");
365
457
  return {
366
458
  success: false,
367
- logs: logger.logs
459
+ logs: logger.getLogs()
368
460
  };
369
461
  }
370
462
  errorState = false;
@@ -375,23 +467,37 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
375
467
  result.error.dispose();
376
468
  return {
377
469
  success: false,
378
- logs: logger.logs
470
+ logs: logger.getPrettyLogs()
379
471
  };
380
472
  } else if ("value" in result) {
473
+ const settled = vm.resolvePromise(result.value);
381
474
  result.value.dispose();
475
+ vm.runtime.executePendingJobs();
476
+ const promiseResult = await settled;
477
+ if (promiseResult.error) {
478
+ const err = vm.dump(promiseResult.error);
479
+ promiseResult.error.dispose();
480
+ const lines = compiled.split("\n").map((l, i) => `${i + 1}: ${l}`);
481
+ logger.error(["Uncaught exception:", err, "\n", lines.join("\n")], "runner");
482
+ return {
483
+ success: false,
484
+ logs: logger.getPrettyLogs()
485
+ };
486
+ }
487
+ promiseResult.value.dispose();
382
488
  if (errorState) {
383
489
  const lines = compiled.split("\n").map((line, index) => `${index + 1}: ${line}`);
384
490
  logger.error(["An error was reported during execution. Compiled code with line numbers:\n", lines.join("\n")], "runner");
385
491
  }
386
492
  return {
387
493
  success: !errorState,
388
- logs: logger.logs
494
+ logs: logger.getPrettyLogs()
389
495
  };
390
496
  } else {
391
497
  logger.error(["Unknown execution result:", result], "runner");
392
498
  return {
393
499
  success: false,
394
- logs: logger.logs
500
+ logs: logger.getPrettyLogs()
395
501
  };
396
502
  }
397
503
  } catch (e) {
@@ -399,7 +505,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
399
505
  }
400
506
  return {
401
507
  success: false,
402
- logs: logger.logs
508
+ logs: logger.getLogs()
403
509
  };
404
510
  }
405
511
  };
@@ -408,13 +514,12 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
408
514
  require$1("dotenv").config();
409
515
  const openai = new openai$1.OpenAI({ baseURL: process.env.OPENAI_API_BASE_URL || void 0, apiKey: process.env.OPENAI_API_KEY || void 0 });
410
516
  let QuickJS = null;
517
+ function createLog(message, source) {
518
+ return { type: "log", args: [message], source };
519
+ }
411
520
  const wrapCode = (apiGlobalName, apiFileDefPath, code) => `
412
521
  (async () => {
413
- try {
414
- ${code}
415
- } catch(err) {
416
- console.error(err);
417
- }
522
+ ${code}
418
523
  })();
419
524
  `;
420
525
  const wrapCodeBlock = (code, codeType = "") => `
@@ -428,13 +533,13 @@ function zodParseJSON(schema) {
428
533
  function createBasePrompt(apiFilePath, apiGlobalName, documentationPath) {
429
534
  const apiText = fs.readFileSync(apiFilePath, "utf8");
430
535
  const documentationText = documentationPath ? fs.readFileSync(documentationPath, "utf8") : "";
431
- const createTaskPrompt = fs.readFileSync("./prompts/create-task-prompt.md", "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
536
+ const createTaskPrompt = fs.readFileSync(path.resolve(__dirname, "../prompts/generate-code-prompt.md"), "utf8").replace("{{DOCUMENTATION}}", documentationText).replace("{{API}}", apiText).replace("{{API_GLOBAL_NAME}}", apiGlobalName || "");
432
537
  return createTaskPrompt;
433
538
  }
434
539
  const runCodeSchema = zod.z.object({
435
540
  code: zod.z.string()
436
541
  });
437
- const checkCodeSchema = zod.z.object({
542
+ zod.z.object({
438
543
  code: zod.z.string()
439
544
  });
440
545
  const submitCodeSchema = zod.z.object({
@@ -456,34 +561,42 @@ const generateCode = async function(instance, queryText, userChatHistory, create
456
561
  if (debug) {
457
562
  console.log("Running code...", code);
458
563
  }
564
+ const checkRes = await instance.checkCode(code);
565
+ if (!checkRes.success) {
566
+ return {
567
+ success: false,
568
+ reason: "Code check failed",
569
+ logs: checkRes.logs
570
+ };
571
+ }
459
572
  const res = await instance.runCode(code);
460
573
  if (hideLogsFromAgent) {
461
574
  res.logs = [];
462
575
  }
463
576
  return res;
464
577
  },
465
- 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.",
578
+ 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.",
466
579
  parse: zodParseJSON(runCodeSchema),
467
- parameters: zodToJsonSchema.zodToJsonSchema(runCodeSchema)
468
- }
469
- },
470
- {
471
- type: "function",
472
- function: {
473
- name: "checkCode",
474
- // @ts-ignore
475
- function: async ({ code }) => {
476
- if (debug) {
477
- console.log("Checking code...", code);
478
- }
479
- const res = await instance.checkCode(code);
480
- return res;
481
- },
482
- description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
483
- parse: zodParseJSON(checkCodeSchema),
484
- parameters: zodToJsonSchema.zodToJsonSchema(checkCodeSchema)
580
+ parameters: runCodeSchema.toJSONSchema()
485
581
  }
486
582
  },
583
+ // {
584
+ // type: "function",
585
+ // function: {
586
+ // name: "checkCode",
587
+ // // @ts-ignore
588
+ // function: async ({code}: {code: string}) => {
589
+ // if(debug) {
590
+ // console.log("Checking code...", code);
591
+ // }
592
+ // const res = await instance.checkCode(code);
593
+ // return res;
594
+ // },
595
+ // description: "Check the provided code for errors or issues without running it. Returns the result of the code check.",
596
+ // parse: zodParseJSON(checkCodeSchema),
597
+ // parameters: checkCodeSchema.toJSONSchema(),
598
+ // }
599
+ // },
487
600
  {
488
601
  type: "function",
489
602
  function: {
@@ -498,14 +611,18 @@ const generateCode = async function(instance, queryText, userChatHistory, create
498
611
  logs: checkRes.logs
499
612
  };
500
613
  }
501
- finalSubmittedCode = code;
502
- return {
503
- success: true
504
- };
614
+ const res = await instance.runCode(code);
615
+ if (hideLogsFromAgent) {
616
+ res.logs = [];
617
+ }
618
+ if (res.success) {
619
+ finalSubmittedCode = code;
620
+ }
621
+ return res;
505
622
  },
506
- 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.",
623
+ 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.",
507
624
  parse: zodParseJSON(submitCodeSchema),
508
- parameters: zodToJsonSchema.zodToJsonSchema(submitCodeSchema)
625
+ parameters: submitCodeSchema.toJSONSchema()
509
626
  }
510
627
  }
511
628
  ];
@@ -527,17 +644,13 @@ const generateCode = async function(instance, queryText, userChatHistory, create
527
644
  ...additionalModelOptions
528
645
  }).on("message", async (message) => {
529
646
  if (debug) {
530
- console.log("Message:", JSON.stringify(message, null, 2));
647
+ if ("reasoning_content" in message) {
648
+ console.log(message.reasoning_content);
649
+ }
531
650
  }
532
651
  newHistoryItems.push(message);
533
652
  }).on("functionToolCall", (functionCall) => {
534
- if (debug) {
535
- console.log("Function Call:", JSON.stringify(functionCall, null, 2));
536
- }
537
653
  }).on("functionToolCallResult", (functionCall) => {
538
- if (debug) {
539
- console.log("Function Call Result:", JSON.stringify(functionCall, null, 2));
540
- }
541
654
  });
542
655
  const finalContent = await runner.finalContent();
543
656
  if (debug) {
@@ -641,7 +754,7 @@ async function createWithAPI(options) {
641
754
  console.error("Unknown failure checking code");
642
755
  return {
643
756
  success: false,
644
- logs: []
757
+ logs: [createLog("Unknown failure checking code", "compiler")]
645
758
  };
646
759
  }
647
760
  if (debug) {
@@ -682,7 +795,7 @@ async function createWithAPI(options) {
682
795
  };
683
796
  }
684
797
  }
685
- const { vm, runCode: runTask, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
798
+ const { vm, runCode: sandbox_runCode, isAsyncProcessRunning } = await createSandbox(QuickJS, apiExports ? {
686
799
  [apiDefFilePath]: apiExports
687
800
  } : void 0, {
688
801
  ...apiGlobals,
@@ -695,7 +808,7 @@ async function createWithAPI(options) {
695
808
  if (debug) {
696
809
  console.log("Running Code:\n", code);
697
810
  }
698
- const res = await runTask(wrapCode(apiGlobalName, apiDefFilePath, code));
811
+ const res = await sandbox_runCode(wrapCode(apiGlobalName, apiDefFilePath, code));
699
812
  if (!res) {
700
813
  console.error("Unknown failure running task");
701
814
  return {
@@ -726,27 +839,35 @@ async function createWithAPI(options) {
726
839
  // generates code and runs it in one step
727
840
  processRequest: async function(userQuery, currentContext = void 0) {
728
841
  if (debug) {
729
- console.log("Query:", userQuery);
842
+ console.log("[debug] Query:", userQuery);
730
843
  }
731
844
  console.time("Generate Task");
845
+ const prompt = createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : "");
732
846
  const generatedCode = await generateCode(
733
847
  instance,
734
848
  userQuery,
735
849
  [],
736
- createTaskPrompt.replace("{{CONTEXT}}", currentContext ? JSON.stringify(currentContext, null, 2) : ""),
850
+ prompt,
737
851
  debug,
738
852
  hideLogsFromAgent,
739
853
  model,
740
854
  additionalModelOptions
741
855
  );
742
856
  console.timeEnd("Generate Task");
743
- console.time("Run Code");
857
+ console.log(`generated code result
858
+ Success?: ${generatedCode?.success}
859
+ Comments: ${generatedCode?.comments}
860
+ Running Code...`);
861
+ console.time("Run Code took");
744
862
  if (generatedCode?.code) {
745
- await instance.runCode(generatedCode.code);
863
+ const codeRunResult = await instance.runCode(generatedCode.code);
864
+ if (!codeRunResult.success) {
865
+ console.error("Error running generated code");
866
+ }
746
867
  } else {
747
868
  console.error("No code generated", generatedCode);
748
869
  }
749
- console.timeEnd("Run Code");
870
+ console.timeEnd("Run Code took");
750
871
  return generatedCode;
751
872
  }
752
873
  };