@saltcorn/copilot 0.5.0 → 0.5.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/user-copilot.js +81 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/copilot",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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))
@@ -466,39 +482,42 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
466
482
  const getCompletionArguments = async (config) => {
467
483
  let tools = [];
468
484
  const sysPrompts = [];
469
- let properties = {};
470
485
 
471
- const tableNames = (config?.tables || []).map((t) => t.table_name);
472
- properties.table_name = {
473
- type: "string",
474
- enum: tableNames,
475
- description: `Which table is this query from. Every query has to select rows from one table, even if it is based on joins from different tables`,
476
- };
477
- properties.sql_id_query = {
478
- type: "string",
479
- description: `An SQL query for this table's primary keys. This must select only the primary keys (even if the user wants a count), for example SELECT ${
480
- tableNames[0][0]
481
- }."${Table.findOne(tableNames[0]).pk_name}" from "${tableNames[0]}" ${
482
- tableNames[0][0]
483
- } JOIN ... where... Use this to join other tables in the database.`,
484
- };
485
- properties.is_count = {
486
- type: "boolean",
487
- description: `Is the only desired output a count? Make this true if the user wants a count of rows`,
488
- };
486
+ if (config.tables.length) {
487
+ let properties = {};
488
+
489
+ const tableNames = (config?.tables || []).map((t) => t.table_name);
490
+ properties.table_name = {
491
+ type: "string",
492
+ enum: tableNames,
493
+ description: `Which table is this query from. Every query has to select rows from one table, even if it is based on joins from different tables`,
494
+ };
495
+ properties.sql_id_query = {
496
+ type: "string",
497
+ description: `An SQL query for this table's primary keys. This must select only the primary keys (even if the user wants a count), for example SELECT ${
498
+ tableNames[0][0]
499
+ }."${Table.findOne(tableNames[0]).pk_name}" from "${tableNames[0]}" ${
500
+ tableNames[0][0]
501
+ } JOIN ... where... Use this to join other tables in the database.`,
502
+ };
503
+ properties.is_count = {
504
+ type: "boolean",
505
+ description: `Is the only desired output a count? Make this true if the user wants a count of rows`,
506
+ };
489
507
 
490
- tools.push({
491
- type: "function",
492
- function: {
493
- name: "TableQuery",
494
- description: `Query a table and show the results to the user in a grid format`,
495
- parameters: {
496
- type: "object",
497
- required: ["table_name", "sql_id_query", "is_count"],
498
- properties,
508
+ tools.push({
509
+ type: "function",
510
+ function: {
511
+ name: "TableQuery",
512
+ description: `Query a table and show the results to the user in a grid format`,
513
+ parameters: {
514
+ type: "object",
515
+ required: ["table_name", "sql_id_query", "is_count"],
516
+ properties,
517
+ },
499
518
  },
500
- },
501
- });
519
+ });
520
+ }
502
521
 
503
522
  for (const action of config?.actions || []) {
504
523
  let properties = {};
@@ -536,18 +555,19 @@ const getCompletionArguments = async (config) => {
536
555
  const systemPrompt =
537
556
  "You are helping users retrieve information and perform actions on a relational database" +
538
557
  config.sys_prompt +
539
- `
540
- If you are generating SQL, Your database the following tables in PostgreSQL:
558
+ (config.tables.length
559
+ ? `
560
+ If you are generating SQL, Your database has the following tables in PostgreSQL:
541
561
 
542
562
  ` +
543
- tables
544
- .map(
545
- (t) => `CREATE TABLE "${t.name}" (${
546
- t.description
547
- ? `
563
+ tables
564
+ .map(
565
+ (t) => `CREATE TABLE "${t.name}" (${
566
+ t.description
567
+ ? `
548
568
  /* ${t.description} */`
549
- : ""
550
- }
569
+ : ""
570
+ }
551
571
  ${t.fields
552
572
  .map(
553
573
  (f) =>
@@ -559,15 +579,16 @@ ${t.fields
559
579
  )
560
580
  .join(",\n")}
561
581
  )`
562
- )
563
- .join(";\n\n") +
564
- `
582
+ )
583
+ .join(";\n\n") +
584
+ `
565
585
 
566
586
  Use the TableQuery tool if the user asks to see, find or count or otherwise access rows from a table that matches what the user is looking for, or if
567
587
  the user is asking for a summary or inference from such rows. The TableQuery query is parametrised by a SQL SELECT query which
568
588
  selects primary key values from the specified table. You can join other tables or use complex logic in the WHERE clause, but you must
569
589
  always return porimary key values from the specified table.
570
- `;
590
+ `
591
+ : "");
571
592
  //console.log("sysprompt", systemPrompt);
572
593
 
573
594
  if (tools.length === 0) tools = undefined;
@@ -600,7 +621,17 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
600
621
  interactions: [{ role: "user", content: userinput }],
601
622
  });
602
623
  }
603
- return await process_interaction(run, userinput, config, req);
624
+ return await process_interaction(run, config, req);
625
+ };
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;
604
635
  };
605
636
 
606
637
  const renderQueryInteraction = async (table, result, config, req) => {
@@ -653,20 +684,13 @@ const renderQueryInteraction = async (table, result, config, req) => {
653
684
  );
654
685
  };
655
686
 
656
- const process_interaction = async (
657
- run,
658
- input,
659
- config,
660
- req,
661
- prevResponses = []
662
- ) => {
687
+ const process_interaction = async (run, config, req, prevResponses = []) => {
663
688
  const complArgs = await getCompletionArguments(config);
664
689
  complArgs.chat = run.context.interactions;
665
690
  //complArgs.debugResult = true;
666
- //console.log(complArgs);
667
- console.log("complArgs", JSON.stringify(complArgs, null, 2));
691
+ //console.log("complArgs", JSON.stringify(complArgs, null, 2));
668
692
 
669
- const answer = await getState().functions.llm_generate.run(input, complArgs);
693
+ const answer = await getState().functions.llm_generate.run("", complArgs);
670
694
  console.log("answer", answer);
671
695
  await addToContext(run, {
672
696
  interactions:
@@ -820,7 +844,7 @@ const process_interaction = async (
820
844
  }
821
845
  }
822
846
  if (hasResult)
823
- return await process_interaction(run, "", config, req, [
847
+ return await process_interaction(run, config, req, [
824
848
  ...prevResponses,
825
849
  ...responses,
826
850
  ]);
@@ -909,5 +933,5 @@ module.exports = {
909
933
  get_state_fields,
910
934
  tableless: true,
911
935
  run,
912
- routes: { interact },
936
+ routes: { interact, delprevrun },
913
937
  };