@saltcorn/copilot 0.4.1 → 0.4.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.
- package/package.json +1 -1
- package/user-copilot.js +103 -12
package/package.json
CHANGED
package/user-copilot.js
CHANGED
|
@@ -68,10 +68,12 @@ const configuration_workflow = (req) =>
|
|
|
68
68
|
viewtemplate: "Show",
|
|
69
69
|
});
|
|
70
70
|
show_view_opts[t.name] = views.map((v) => v.name);
|
|
71
|
-
const lviews = await View.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const lviews = await View.find_table_views_where(
|
|
72
|
+
t.id,
|
|
73
|
+
({ state_fields, viewrow }) =>
|
|
74
|
+
viewrow.viewtemplate !== "Edit" &&
|
|
75
|
+
state_fields.every((sf) => !sf.required)
|
|
76
|
+
);
|
|
75
77
|
list_view_opts[t.name] = lviews.map((v) => v.name);
|
|
76
78
|
}
|
|
77
79
|
return new Form({
|
|
@@ -203,6 +205,20 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
|
|
|
203
205
|
"Copilot"
|
|
204
206
|
)
|
|
205
207
|
);
|
|
208
|
+
} else if (tool_call.function.name.startsWith("Query")) {
|
|
209
|
+
const query = JSON.parse(tool_call.function.arguments);
|
|
210
|
+
const queryText = query.sql_id_query
|
|
211
|
+
? query.sql_id_query
|
|
212
|
+
: JSON.stringify(query, null, 2);
|
|
213
|
+
interactMarkups.push(
|
|
214
|
+
wrapSegment(
|
|
215
|
+
wrapCard(
|
|
216
|
+
"Query " + tool_call.function.name.replace("Query", ""),
|
|
217
|
+
pre(queryText)
|
|
218
|
+
),
|
|
219
|
+
"Copilot"
|
|
220
|
+
)
|
|
221
|
+
);
|
|
206
222
|
}
|
|
207
223
|
}
|
|
208
224
|
} else
|
|
@@ -479,7 +495,10 @@ const getCompletionArguments = async (config) => {
|
|
|
479
495
|
];
|
|
480
496
|
} else Object.assign(fieldProperties(field), properties[field.name]);
|
|
481
497
|
});
|
|
482
|
-
|
|
498
|
+
properties.sql_id_query = {
|
|
499
|
+
type: "string",
|
|
500
|
+
description: `An SQL query for this table's primary keys (${table.pk_name}). This must select only the primary keys, for example SELECT ${table.name[0]}."${table.pk_name}" from "${table.name}" ${table.name[0]} JOIN ... where... Use this to join other tables in the database. If you use sql_id_query, use it alone, do not combine with other field queries. Any other fields you want to filter on must be accessed in the WHERE clause`,
|
|
501
|
+
};
|
|
483
502
|
tools.push({
|
|
484
503
|
type: "function",
|
|
485
504
|
function: {
|
|
@@ -524,9 +543,39 @@ const getCompletionArguments = async (config) => {
|
|
|
524
543
|
},
|
|
525
544
|
});
|
|
526
545
|
}
|
|
546
|
+
const tables = (await Table.find({})).filter(
|
|
547
|
+
(t) => !t.external && !t.provider_name
|
|
548
|
+
);
|
|
549
|
+
const schemaPrefix = db.getTenantSchemaPrefix();
|
|
527
550
|
const systemPrompt =
|
|
528
551
|
"You are helping users retrieve information and perform actions on a relational database" +
|
|
529
|
-
config.sys_prompt
|
|
552
|
+
config.sys_prompt +
|
|
553
|
+
`
|
|
554
|
+
If you are generating SQL, Your database the following tables in PostgreSQL:
|
|
555
|
+
|
|
556
|
+
` +
|
|
557
|
+
tables
|
|
558
|
+
.map(
|
|
559
|
+
(t) => `CREATE TABLE "${t.name}" (${
|
|
560
|
+
t.description
|
|
561
|
+
? `
|
|
562
|
+
/* ${t.description} */`
|
|
563
|
+
: ""
|
|
564
|
+
}
|
|
565
|
+
${t.fields
|
|
566
|
+
.map(
|
|
567
|
+
(f) =>
|
|
568
|
+
` "${f.name}" ${
|
|
569
|
+
f.primary_key && f.type?.name === "Integer"
|
|
570
|
+
? "SERIAL PRIMARY KEY"
|
|
571
|
+
: f.sql_type.replace(schemaPrefix, "")
|
|
572
|
+
}`
|
|
573
|
+
)
|
|
574
|
+
.join(",\n")}
|
|
575
|
+
)`
|
|
576
|
+
)
|
|
577
|
+
.join(";\n\n");
|
|
578
|
+
//console.log("sysprompt", systemPrompt);
|
|
530
579
|
|
|
531
580
|
if (tools.length === 0) tools = undefined;
|
|
532
581
|
return { tools, systemPrompt };
|
|
@@ -647,7 +696,10 @@ const process_interaction = async (
|
|
|
647
696
|
result,
|
|
648
697
|
});
|
|
649
698
|
|
|
650
|
-
if (
|
|
699
|
+
if (
|
|
700
|
+
(typeof result === "object" && Object.keys(result || {}).length) ||
|
|
701
|
+
typeof result === "string"
|
|
702
|
+
) {
|
|
651
703
|
responses.push(
|
|
652
704
|
wrapSegment(
|
|
653
705
|
wrapCard(
|
|
@@ -665,7 +717,10 @@ const process_interaction = async (
|
|
|
665
717
|
role: "tool",
|
|
666
718
|
tool_call_id: tool_call.id,
|
|
667
719
|
name: tool_call.function.name,
|
|
668
|
-
content:
|
|
720
|
+
content:
|
|
721
|
+
result && typeof result !== "string"
|
|
722
|
+
? JSON.stringify(result)
|
|
723
|
+
: result || "Action run",
|
|
669
724
|
},
|
|
670
725
|
],
|
|
671
726
|
});
|
|
@@ -674,10 +729,46 @@ const process_interaction = async (
|
|
|
674
729
|
name: tool_call.function.name.replace("Query", ""),
|
|
675
730
|
});
|
|
676
731
|
const query = JSON.parse(tool_call.function.arguments);
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
732
|
+
let result;
|
|
733
|
+
if (query.sql_id_query) {
|
|
734
|
+
const is_sqlite = db.isSQLite;
|
|
735
|
+
|
|
736
|
+
const client = is_sqlite ? db : await db.getClient();
|
|
737
|
+
await client.query(`BEGIN;`);
|
|
738
|
+
if (!is_sqlite) {
|
|
739
|
+
await client.query(
|
|
740
|
+
`SET LOCAL search_path TO "${db.getTenantSchema()}";`
|
|
741
|
+
);
|
|
742
|
+
await client.query(
|
|
743
|
+
`SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;`
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const { rows } = await client.query(query.sql_id_query);
|
|
748
|
+
await client.query(`ROLLBACK;`);
|
|
749
|
+
|
|
750
|
+
if (!is_sqlite) client.release(true);
|
|
751
|
+
result = await table.getRows(
|
|
752
|
+
{ [table.pk_name]: { in: rows.map((r) => r[table.pk_name]) } },
|
|
753
|
+
{
|
|
754
|
+
forUser: req.user,
|
|
755
|
+
forPublic: !req.user,
|
|
756
|
+
}
|
|
757
|
+
);
|
|
758
|
+
responses.push(
|
|
759
|
+
wrapSegment(
|
|
760
|
+
wrapCard(
|
|
761
|
+
"Query " + tool_call.function.name.replace("Query", ""),
|
|
762
|
+
pre(query.sql_id_query)
|
|
763
|
+
),
|
|
764
|
+
"Copilot"
|
|
765
|
+
)
|
|
766
|
+
);
|
|
767
|
+
} else
|
|
768
|
+
result = await table.getRows(query, {
|
|
769
|
+
forUser: req.user,
|
|
770
|
+
forPublic: !req.user,
|
|
771
|
+
});
|
|
681
772
|
await addToContext(run, {
|
|
682
773
|
interactions: [
|
|
683
774
|
{
|