@saltcorn/copilot 0.5.1 → 0.5.3

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.
@@ -361,90 +361,4 @@ function escapeHtml(unsafe) {
361
361
  .replace(/'/g, "'");
362
362
  }
363
363
 
364
- parseHTML(`<!DOCTYPE html>
365
- <html lang="en">
366
- <head>
367
- <meta charset="UTF-8">
368
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
369
- <title>Popcorn Beer - Unleash the Flavor Explosion!</title>
370
- <link href="https://stackpath.bootstrapcdn.com/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
371
- </head>
372
- <body>
373
-
374
- <header class="bg-warning text-dark py-5">
375
- <div class="container text-center">
376
- <h1 class="display-4">Popcorn Beer</h1>
377
- <p class="lead">Unleash the Flavor Explosion!</p>
378
- </div>
379
- </header>
380
-
381
- <section class="py-5">
382
- <div class="container">
383
- <div class="row align-items-center">
384
- <div class="col-md-6">
385
- <img src="your-image-url.jpg" alt="Popcorn Beer" class="img-fluid rounded">
386
- </div>
387
- <div class="col-md-6">
388
- <h2>Discover the Unique Taste</h2>
389
- <p>Introducing our popcorn-flavored beer, a delightful fusion of classic beer with a twist of popcorn essence. Experience the taste sensation that will keep you coming back for more.</p>
390
- <a href="#purchase" class="btn btn-warning btn-lg mt-3">Buy Now</a>
391
- </div>
392
- </div>
393
- </div>
394
- </section>
395
-
396
- <section class="bg-light py-5">
397
- <div class="container">
398
- <h2 class="text-center mb-4">Why Choose Popcorn Beer?</h2>
399
- <div class="row">
400
- <div class="col-lg-4">
401
- <div class="card mb-4">
402
- <div class="card-body text-center">
403
- <h5 class="card-title">Unique Flavor</h5>
404
- <p class="card-text">A perfect blend of beer and popcorn that tantalizes your taste buds.</p>
405
- </div>
406
- </div>
407
- </div>
408
- <div class="col-lg-4">
409
- <div class="card mb-4">
410
- <div class="card-body text-center">
411
- <h5 class="card-title">Premium Ingredients</h5>
412
- <p class="card-text">Crafted with the finest ingredients for an unparalleled taste.</p>
413
- </div>
414
- </div>
415
- </div>
416
- <div class="col-lg-4">
417
- <div class="card mb-4">
418
- <div class="card-body text-center">
419
- <h5 class="card-title">Perfect for Any Occasion</h5>
420
- <p class="card-text">Whether it's a movie night or a party, Popcorn Beer is your go-to drink.</p>
421
- </div>
422
- </div>
423
- </div>
424
- </div>
425
- </div>
426
- </section>
427
-
428
- <section id="purchase" class="py-5">
429
- <div class="container text-center">
430
- <h2>Get Your Popcorn Beer Today!</h2>
431
- <p class="mb-4">Available for purchase online and in select stores near you.</p>
432
- <a href="shop.html" class="btn btn-warning btn-lg">Shop Now</a>
433
- </div>
434
- </section>
435
-
436
- <footer class="bg-dark text-white py-4">
437
- <div class="container text-center">
438
- <p>&copy; 2023 Popcorn Beer. All rights reserved.</p>
439
- <ul class="list-inline">
440
- <li class="list-inline-item"><a href="#" class="text-white">Privacy Policy</a></li>
441
- <li class="list-inline-item"><a href="#" class="text-white">Terms of Service</a></li>
442
- <li class="list-inline-item"><a href="#" class="text-white">Contact Us</a></li>
443
- </ul>
444
- </div>
445
- </footer>
446
-
447
- <script src="https://stackpath.bootstrapcdn.com/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
448
- </body>`);
449
-
450
364
  module.exports = GeneratePage;
package/chat-copilot.js CHANGED
@@ -337,23 +337,24 @@ const execute = async (table_id, viewname, config, body, { req }) => {
337
337
 
338
338
  const fcall = run.context.funcalls[fcall_id];
339
339
  const actionClass = classesWithSkills().find(
340
- (ac) => ac.function_name === fcall.name
340
+ (ac) => ac.function_name === (fcall.name || fcall.toolName)
341
341
  );
342
342
  let result;
343
+ const args = fcall.arguments ? JSON.parse(fcall.arguments) : fcall.input;
344
+
343
345
  if (actionClass.follow_on_generate) {
344
346
  const toolCallIndex = run.context.interactions.findIndex(
345
- (i) => i.tool_call_id === fcall_id
347
+ (i) =>
348
+ i.tool_call_id === fcall_id ||
349
+ (Array.isArray(i.content) &&
350
+ i.content.some((c) => c.toolCallId === fcall_id))
346
351
  );
347
352
  const follow_on_gen = run.context.interactions.find(
348
353
  (i, ix) => i.role === "assistant" && ix > toolCallIndex
349
354
  );
350
- result = await actionClass.execute(
351
- JSON.parse(fcall.arguments),
352
- req,
353
- follow_on_gen.content
354
- );
355
+ result = await actionClass.execute(args, req, follow_on_gen.content);
355
356
  } else {
356
- result = await actionClass.execute(JSON.parse(fcall.arguments), req);
357
+ result = await actionClass.execute(args, req);
357
358
  }
358
359
  await addToContext(run, { implemented_fcall_ids: [fcall_id] });
359
360
  return { json: { success: "ok", fcall_id, ...(result || {}) } };
@@ -390,27 +391,50 @@ const interact = async (table_id, viewname, config, body, { req }) => {
390
391
  userinput,
391
392
  complArgs
392
393
  );
393
- await addToContext(run, {
394
- interactions:
395
- typeof answer === "object" && answer.tool_calls
396
- ? [
397
- { role: "assistant", tool_calls: answer.tool_calls },
398
- ...answer.tool_calls.map((tc) => ({
399
- role: "tool",
400
- tool_call_id: tc.id,
401
- name: tc.function.name,
402
- content: "Action suggested to user.",
403
- })),
404
- ]
405
- : [{ role: "assistant", content: answer }],
406
- });
407
- console.log("answer", answer);
408
-
394
+ if (answer.ai_sdk)
395
+ for (const tool_call of answer.tool_calls)
396
+ await addToContext(run, {
397
+ interactions: [
398
+ ...answer.messages,
399
+ {
400
+ role: "tool",
401
+ content: [
402
+ {
403
+ type: "tool-result",
404
+ toolCallId: tool_call.toolCallId,
405
+ toolName: tool_call.toolName,
406
+ output: {
407
+ type: "text",
408
+ value: "Action suggested to user.",
409
+ },
410
+ },
411
+ ],
412
+ },
413
+ ],
414
+ });
415
+ else
416
+ await addToContext(run, {
417
+ interactions:
418
+ typeof answer === "object" && answer.tool_calls
419
+ ? [
420
+ { role: "assistant", tool_calls: answer.tool_calls },
421
+ ...answer.tool_calls.map((tc) => ({
422
+ role: "tool",
423
+ tool_call_id: tc.id || tc.toolCallId,
424
+ name: tc.function?.name || tc.toolName,
425
+ content: "Action suggested to user.",
426
+ })),
427
+ ]
428
+ : [{ role: "assistant", content: answer }],
429
+ });
409
430
  if (typeof answer === "object" && answer.tool_calls) {
410
431
  const actions = [];
411
432
  for (const tool_call of answer.tool_calls) {
412
433
  await addToContext(run, {
413
- funcalls: { [tool_call.id]: tool_call.function },
434
+ funcalls: {
435
+ [tool_call.id || tool_call.toolCallId]:
436
+ tool_call.function || tool_call,
437
+ },
414
438
  });
415
439
 
416
440
  const followOnGen = await getFollowOnGeneration(tool_call);
@@ -433,7 +457,6 @@ const interact = async (table_id, viewname, config, body, { req }) => {
433
457
  }
434
458
  );
435
459
 
436
- console.log("follow on answer", follow_on_answer);
437
460
 
438
461
  await addToContext(run, {
439
462
  interactions: [
@@ -465,11 +488,13 @@ const interact = async (table_id, viewname, config, body, { req }) => {
465
488
  };
466
489
 
467
490
  const getFollowOnGeneration = async (tool_call) => {
468
- const fname = tool_call.function.name;
491
+ const fname = tool_call.function?.name || tool_call.toolName;
469
492
  const actionClass = classesWithSkills().find(
470
493
  (ac) => ac.function_name === fname
471
494
  );
472
- const args = JSON.parse(tool_call.function.arguments);
495
+ const args = tool_call.function?.arguments
496
+ ? JSON.parse(tool_call.function?.arguments)
497
+ : tool_call.input;
473
498
 
474
499
  if (actionClass.follow_on_generate) {
475
500
  return await actionClass.follow_on_generate(args);
@@ -483,11 +508,13 @@ const renderToolcall = async (
483
508
  run,
484
509
  follow_on_answer
485
510
  ) => {
486
- const fname = tool_call.function.name;
511
+ const fname = tool_call.function?.name || tool_call.toolName;
487
512
  const actionClass = classesWithSkills().find(
488
513
  (ac) => ac.function_name === fname
489
514
  );
490
- const args = JSON.parse(tool_call.function.arguments);
515
+ const args = tool_call.function?.arguments
516
+ ? JSON.parse(tool_call.function.arguments)
517
+ : tool_call.input;
491
518
 
492
519
  const inner_markup = await actionClass.render_html(args, follow_on_answer);
493
520
  return wrapAction(
@@ -529,7 +556,9 @@ const wrapAction = (
529
556
  type: "button",
530
557
  id: "exec-" + tool_call.id,
531
558
  class: "btn btn-primary d-block mt-3 float-end",
532
- onclick: `press_store_button(this, true);view_post('${viewname}', 'execute', {fcall_id: '${tool_call.id}', run_id: ${run.id}}, processExecuteResponse)`,
559
+ onclick: `press_store_button(this, true);view_post('${viewname}', 'execute', {fcall_id: '${
560
+ tool_call.id || tool_call.toolCallId
561
+ }', run_id: ${run.id}}, processExecuteResponse)`,
533
562
  },
534
563
  "Apply"
535
564
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/copilot",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "AI assistant for building Saltcorn applications",
5
5
  "main": "index.js",
6
6
  "dependencies": {
package/user-copilot.js CHANGED
@@ -362,7 +362,14 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
362
362
  onclick: `set_state_field('run_id',${run.id})`,
363
363
  class: "prevcopilotrun border p-2",
364
364
  },
365
- localeDateTime(run.started_at),
365
+ div(
366
+ { class: "d-flex justify-content-between" },
367
+ localeDateTime(run.started_at),
368
+ i({
369
+ class: "far fa-trash-alt",
370
+ onclick: `delprevrun(event, ${run.id})`,
371
+ })
372
+ ),
366
373
 
367
374
  p(
368
375
  { class: "prevrun_content" },
@@ -397,6 +404,8 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
397
404
  div.interaction-segment p {margin-bottom: 0px;}
398
405
  div.interaction-segment div.card {margin-top: 0.5rem;}
399
406
  div.prevcopilotrun:hover {cursor: pointer; background-color: var(--tblr-secondary-bg-subtle, var(--bs-secondary-bg-subtle, gray));}
407
+ div.prevcopilotrun i.fa-trash-alt {display: none;}
408
+ div.prevcopilotrun:hover i.fa-trash-alt {display: block;}
400
409
  .copilot-entry .submit-button:hover { cursor: pointer}
401
410
 
402
411
  .copilot-entry .submit-button {
@@ -430,6 +439,13 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
430
439
  btn.css({ width: "" }).prop("disabled", false);
431
440
  btn.removeData("old-text");
432
441
  }
442
+ function delprevrun(e, runid) {
443
+ e.preventDefault();
444
+ e.stopPropagation();
445
+ view_post('${viewname}', 'delprevrun', {run_id:runid})
446
+ $(e.target).closest(".prevcopilotrun").remove()
447
+ return false;
448
+ }
433
449
  function processExecuteResponse(res) {
434
450
  const btn = $("#exec-"+res.fcall_id)
435
451
  restore_old_button_elem($("#exec-"+res.fcall_id))
@@ -608,6 +624,16 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
608
624
  return await process_interaction(run, config, req);
609
625
  };
610
626
 
627
+ const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
628
+ const { run_id } = body;
629
+ let run;
630
+
631
+ run = await WorkflowRun.findOne({ id: +run_id });
632
+ await run.delete();
633
+
634
+ return;
635
+ };
636
+
611
637
  const renderQueryInteraction = async (table, result, config, req) => {
612
638
  if (typeof result === "number")
613
639
  return wrapSegment(
@@ -907,5 +933,5 @@ module.exports = {
907
933
  get_state_fields,
908
934
  tableless: true,
909
935
  run,
910
- routes: { interact },
936
+ routes: { interact, delprevrun },
911
937
  };