@saltcorn/sql 0.4.3 → 0.5.0
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/agent-skill.js +116 -0
- package/index.js +19 -11
- package/package.json +3 -3
package/agent-skill.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const { div, pre, a } = require("@saltcorn/markup/tags");
|
|
2
|
+
const Workflow = require("@saltcorn/data/models/workflow");
|
|
3
|
+
const Form = require("@saltcorn/data/models/form");
|
|
4
|
+
const Table = require("@saltcorn/data/models/table");
|
|
5
|
+
const View = require("@saltcorn/data/models/view");
|
|
6
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
7
|
+
const { getState } = require("@saltcorn/data/db/state");
|
|
8
|
+
const db = require("@saltcorn/data/db");
|
|
9
|
+
const { eval_expression } = require("@saltcorn/data/models/expression");
|
|
10
|
+
const { interpolate } = require("@saltcorn/data/utils");
|
|
11
|
+
|
|
12
|
+
//const { fieldProperties } = require("./helpers");
|
|
13
|
+
|
|
14
|
+
class SQLQuerySkill {
|
|
15
|
+
static skill_name = "SQL query";
|
|
16
|
+
|
|
17
|
+
get skill_label() {
|
|
18
|
+
return "SQL Query";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
constructor(cfg) {
|
|
22
|
+
Object.assign(this, cfg);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async runQuery({ triggering_row, user }) {
|
|
26
|
+
const row = triggering_row;
|
|
27
|
+
const read_only = true;
|
|
28
|
+
const is_sqlite = db.isSQLite;
|
|
29
|
+
|
|
30
|
+
const phValues = [];
|
|
31
|
+
(this.query_parameters || "")
|
|
32
|
+
.split(",")
|
|
33
|
+
.filter((s) => s)
|
|
34
|
+
.forEach((sp0) => {
|
|
35
|
+
const sp = sp0.trim();
|
|
36
|
+
if (sp.startsWith("user.")) {
|
|
37
|
+
phValues.push(eval_expression(sp, {}, user));
|
|
38
|
+
} else if (typeof row[sp] === "undefined") phValues.push(null);
|
|
39
|
+
else phValues.push(row[sp]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const client = is_sqlite ? db : await db.getClient();
|
|
43
|
+
await client.query(`BEGIN;`);
|
|
44
|
+
if (!is_sqlite) {
|
|
45
|
+
await client.query(`SET LOCAL search_path TO "${db.getTenantSchema()}";`);
|
|
46
|
+
if (read_only)
|
|
47
|
+
await client.query(
|
|
48
|
+
`SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const qres = await client.query(this.sql, phValues);
|
|
52
|
+
|
|
53
|
+
await client.query(`COMMIT;`);
|
|
54
|
+
|
|
55
|
+
if (!is_sqlite) client.release(true);
|
|
56
|
+
|
|
57
|
+
if (this.row_format) {
|
|
58
|
+
return qres.rows
|
|
59
|
+
.map((r) => interpolate(this.row_format, r, user))
|
|
60
|
+
.join("\n\n");
|
|
61
|
+
}
|
|
62
|
+
return JSON.stringify(qres.rows);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async systemPrompt({ triggering_row, user }) {
|
|
66
|
+
if (this.mode === "Preload into system prompt") {
|
|
67
|
+
const rows = await this.runQuery({ triggering_row, user });
|
|
68
|
+
return `${this.add_sys_prompt}: ${rows}`;
|
|
69
|
+
}
|
|
70
|
+
return `${this.add_sys_prompt}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static async configFields() {
|
|
74
|
+
return [
|
|
75
|
+
{
|
|
76
|
+
name: "mode",
|
|
77
|
+
label: "Mode",
|
|
78
|
+
type: "String",
|
|
79
|
+
required: true,
|
|
80
|
+
attributes: { options: [/*"Tool",*/ "Preload into system prompt"] },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "sql",
|
|
84
|
+
label: "SQL",
|
|
85
|
+
input_type: "code",
|
|
86
|
+
attributes: { mode: "text/x-sql" },
|
|
87
|
+
sublabel:
|
|
88
|
+
"Refer to row parameters in the order below with <code>$1</code>, <code>$2</code> etc",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "query_parameters",
|
|
92
|
+
label: "Query parameters",
|
|
93
|
+
sublabel:
|
|
94
|
+
"Comma separated list of variables to use as SQL query parameters. User variables can be used as <code>user.id</code> etc",
|
|
95
|
+
type: "String",
|
|
96
|
+
//showIf: { mode: "Tool" },
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "add_sys_prompt",
|
|
100
|
+
label: "Additional prompt",
|
|
101
|
+
type: "String",
|
|
102
|
+
fieldview: "textarea",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "row_format",
|
|
106
|
+
label: "Row format",
|
|
107
|
+
type: "String",
|
|
108
|
+
fieldview: "textarea",
|
|
109
|
+
sublabel:
|
|
110
|
+
"Format of text to send to LLM, use <code>{{ }}</code> to access row fields. If not set, rows will be sent as JSON",
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = SQLQuerySkill;
|
package/index.js
CHANGED
|
@@ -96,18 +96,23 @@ const run = async (
|
|
|
96
96
|
} else if (typeof state[sp] === "undefined") phValues.push(null);
|
|
97
97
|
else phValues.push(state[sp]);
|
|
98
98
|
});
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
let qres, client;
|
|
100
|
+
try {
|
|
101
|
+
client = is_sqlite ? db : await db.getClient();
|
|
102
|
+
await client.query(`BEGIN;`);
|
|
103
|
+
if (!is_sqlite) {
|
|
104
|
+
await client.query(`SET LOCAL search_path TO "${db.getTenantSchema()}";`);
|
|
105
|
+
await client.query(
|
|
106
|
+
`SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
qres = await client.query(sql, phValues);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
throw e;
|
|
112
|
+
} finally {
|
|
113
|
+
await client.query(`ROLLBACK;`);
|
|
114
|
+
if (!is_sqlite) client.release(true);
|
|
105
115
|
}
|
|
106
|
-
const qres = await client.query(sql, phValues);
|
|
107
|
-
|
|
108
|
-
await client.query(`ROLLBACK;`);
|
|
109
|
-
|
|
110
|
-
if (!is_sqlite) client.release(true);
|
|
111
116
|
switch (output_type) {
|
|
112
117
|
case "HTML":
|
|
113
118
|
const template = _.template(html_code || "", {
|
|
@@ -133,6 +138,9 @@ module.exports = {
|
|
|
133
138
|
plugin_name: "sql",
|
|
134
139
|
actions: require("./action.js"),
|
|
135
140
|
table_providers: require("./table-provider.js"),
|
|
141
|
+
exchange: {
|
|
142
|
+
agent_skills: [require("./agent-skill.js")],
|
|
143
|
+
},
|
|
136
144
|
functions: {
|
|
137
145
|
sqlQuery: {
|
|
138
146
|
run: async (query, parameters) => {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Actions and views based on SQL",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@saltcorn/markup": "^0.6.0",
|
|
8
8
|
"@saltcorn/data": "^0.6.0",
|
|
9
9
|
"underscore": "1.13.6",
|
|
10
|
-
"node-sql-parser": "
|
|
10
|
+
"node-sql-parser": "5.3.10",
|
|
11
11
|
"sqlstring": "^2.3.3"
|
|
12
12
|
},
|
|
13
13
|
"author": "Tom Nielsen",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"eslintConfig": {
|
|
16
16
|
"extends": "eslint:recommended",
|
|
17
17
|
"parserOptions": {
|
|
18
|
-
"ecmaVersion":
|
|
18
|
+
"ecmaVersion": 2022
|
|
19
19
|
},
|
|
20
20
|
"env": {
|
|
21
21
|
"node": true,
|