@saltcorn/copilot 0.4.3 → 0.4.5
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/actions/generate-tables.js +3 -3
- package/actions/generate-workflow.js +10 -3
- package/common.js +13 -1
- package/package.json +1 -1
- package/user-copilot.js +93 -52
|
@@ -17,7 +17,7 @@ class GenerateTables {
|
|
|
17
17
|
const types = Object.values(getState().types);
|
|
18
18
|
const fieldTypeCfg = types.map((ty) => {
|
|
19
19
|
const properties = {
|
|
20
|
-
data_type: {
|
|
20
|
+
data_type: { type: "string", enum: [ty.name] },
|
|
21
21
|
};
|
|
22
22
|
const attrs = apply(ty.attributes, {}) || [];
|
|
23
23
|
if (Array.isArray(attrs))
|
|
@@ -40,7 +40,7 @@ class GenerateTables {
|
|
|
40
40
|
description:
|
|
41
41
|
"A foreign key to a different table. This will reference the primary key on another table.",
|
|
42
42
|
properties: {
|
|
43
|
-
data_type: {
|
|
43
|
+
data_type: { type: "string", enum: ["ForeignKey"] },
|
|
44
44
|
reference_table: {
|
|
45
45
|
type: "string",
|
|
46
46
|
description: "Name of the table being referenced",
|
|
@@ -52,7 +52,7 @@ class GenerateTables {
|
|
|
52
52
|
description:
|
|
53
53
|
"A reference (file path) to a file on disk. This can be used for example to hold images or documents",
|
|
54
54
|
properties: {
|
|
55
|
-
data_type: {
|
|
55
|
+
data_type: { type: "string", enum: ["File"] },
|
|
56
56
|
},
|
|
57
57
|
});
|
|
58
58
|
return {
|
|
@@ -16,7 +16,9 @@ const steps = async () => {
|
|
|
16
16
|
);
|
|
17
17
|
|
|
18
18
|
const stepTypeAndCfg = Object.keys(actionExplainers).map((actionName) => {
|
|
19
|
-
const properties = {
|
|
19
|
+
const properties = {
|
|
20
|
+
step_type: { type: "string", enum: [actionName] }
|
|
21
|
+
};
|
|
20
22
|
const myFields = actionFields.filter(
|
|
21
23
|
(f) => f.showIf?.wf_action_name === actionName
|
|
22
24
|
);
|
|
@@ -37,7 +39,9 @@ const steps = async () => {
|
|
|
37
39
|
});
|
|
38
40
|
for (const [actionName, action] of stateActionList) {
|
|
39
41
|
try {
|
|
40
|
-
const properties = {
|
|
42
|
+
const properties = {
|
|
43
|
+
step_type: { type: "string", enum: [actionName] }
|
|
44
|
+
};
|
|
41
45
|
const cfgFields = await getActionConfigFields(action, null, {
|
|
42
46
|
mode: "workflow",
|
|
43
47
|
copilot: true,
|
|
@@ -69,7 +73,10 @@ const steps = async () => {
|
|
|
69
73
|
//TODO workflows
|
|
70
74
|
for (const trigger of triggers) {
|
|
71
75
|
const properties = {
|
|
72
|
-
step_type: {
|
|
76
|
+
step_type: {
|
|
77
|
+
type: "string",
|
|
78
|
+
enum: [trigger.name],
|
|
79
|
+
},
|
|
73
80
|
};
|
|
74
81
|
if (trigger.table_id) {
|
|
75
82
|
const table = Table.findOne({ id: trigger.table_id });
|
package/common.js
CHANGED
|
@@ -99,7 +99,19 @@ const fieldProperties = (field) => {
|
|
|
99
99
|
if (field.options) props.enum = toArrayOfStrings(field.options);
|
|
100
100
|
break;
|
|
101
101
|
}
|
|
102
|
+
if (!props.type) {
|
|
103
|
+
switch (field.input_type) {
|
|
104
|
+
case "code":
|
|
105
|
+
props.type = "string";
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
102
109
|
return props;
|
|
103
110
|
};
|
|
104
111
|
|
|
105
|
-
module.exports = {
|
|
112
|
+
module.exports = {
|
|
113
|
+
getCompletion,
|
|
114
|
+
getPromptFromTemplate,
|
|
115
|
+
incompleteCfgMsg,
|
|
116
|
+
fieldProperties,
|
|
117
|
+
};
|
package/package.json
CHANGED
package/user-copilot.js
CHANGED
|
@@ -196,6 +196,17 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
|
|
|
196
196
|
case "assistant":
|
|
197
197
|
case "system":
|
|
198
198
|
if (interact.tool_calls) {
|
|
199
|
+
if (interact.content) {
|
|
200
|
+
interactMarkups.push(
|
|
201
|
+
div(
|
|
202
|
+
{ class: "interaction-segment" },
|
|
203
|
+
span({ class: "badge bg-secondary" }, "Copilot"),
|
|
204
|
+
typeof interact.content === "string"
|
|
205
|
+
? md.render(interact.content)
|
|
206
|
+
: interact.content
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
}
|
|
199
210
|
for (const tool_call of interact.tool_calls) {
|
|
200
211
|
const action = config.actions.find(
|
|
201
212
|
(a) => a.trigger_name === tool_call.function.name
|
|
@@ -212,17 +223,14 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
|
|
|
212
223
|
"Copilot"
|
|
213
224
|
)
|
|
214
225
|
);
|
|
215
|
-
} else if (tool_call.function.name
|
|
226
|
+
} else if (tool_call.function.name === "TableQuery") {
|
|
216
227
|
const query = JSON.parse(tool_call.function.arguments);
|
|
217
228
|
const queryText = query.sql_id_query
|
|
218
229
|
? query.sql_id_query
|
|
219
230
|
: JSON.stringify(query, null, 2);
|
|
220
231
|
interactMarkups.push(
|
|
221
232
|
wrapSegment(
|
|
222
|
-
wrapCard(
|
|
223
|
-
"Query " + tool_call.function.name.replace("Query", ""),
|
|
224
|
-
pre(queryText)
|
|
225
|
-
),
|
|
233
|
+
wrapCard("Query " + query.table_name, pre(queryText)),
|
|
226
234
|
"Copilot"
|
|
227
235
|
)
|
|
228
236
|
);
|
|
@@ -240,25 +248,40 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
|
|
|
240
248
|
);
|
|
241
249
|
break;
|
|
242
250
|
case "tool":
|
|
243
|
-
if (interact.name
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
table,
|
|
250
|
-
JSON.parse(interact.content),
|
|
251
|
-
config,
|
|
252
|
-
req
|
|
251
|
+
if (interact.name === "TableQuery") {
|
|
252
|
+
const tool_call = run.context.interactions
|
|
253
|
+
.map(
|
|
254
|
+
(i) =>
|
|
255
|
+
i.tool_calls &&
|
|
256
|
+
i.tool_calls.find((tc) => tc.id === interact.tool_call_id)
|
|
253
257
|
)
|
|
254
|
-
|
|
258
|
+
.filter(Boolean)[0];
|
|
259
|
+
if (tool_call) {
|
|
260
|
+
const args = JSON.parse(tool_call.function.arguments);
|
|
261
|
+
const table = Table.findOne(args.table_name);
|
|
262
|
+
interactMarkups.push(
|
|
263
|
+
await renderQueryInteraction(
|
|
264
|
+
table,
|
|
265
|
+
JSON.parse(interact.content),
|
|
266
|
+
config,
|
|
267
|
+
req
|
|
268
|
+
)
|
|
269
|
+
);
|
|
270
|
+
}
|
|
255
271
|
} else if (interact.content !== "Action run") {
|
|
272
|
+
let markupContent;
|
|
273
|
+
try {
|
|
274
|
+
markupContent = JSON.stringify(
|
|
275
|
+
JSON.parse(interact.content),
|
|
276
|
+
null,
|
|
277
|
+
2
|
|
278
|
+
);
|
|
279
|
+
} catch {
|
|
280
|
+
markupContent = interact.content;
|
|
281
|
+
}
|
|
256
282
|
interactMarkups.push(
|
|
257
283
|
wrapSegment(
|
|
258
|
-
wrapCard(
|
|
259
|
-
interact.name,
|
|
260
|
-
pre(JSON.stringify(JSON.parse(interact.content), null, 2))
|
|
261
|
-
),
|
|
284
|
+
wrapCard(interact.name, pre(markupContent)),
|
|
262
285
|
"Copilot"
|
|
263
286
|
)
|
|
264
287
|
);
|
|
@@ -443,32 +466,40 @@ const run = async (table_id, viewname, config, state, { res, req }) => {
|
|
|
443
466
|
const getCompletionArguments = async (config) => {
|
|
444
467
|
let tools = [];
|
|
445
468
|
const sysPrompts = [];
|
|
446
|
-
|
|
447
|
-
let properties = {};
|
|
469
|
+
let properties = {};
|
|
448
470
|
|
|
449
|
-
|
|
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
|
+
};
|
|
450
489
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
type: "function",
|
|
461
|
-
function: {
|
|
462
|
-
name: "Query" + table.name,
|
|
463
|
-
description: `Query the ${table.name} table and show the results to the user in a grid format`,
|
|
464
|
-
parameters: {
|
|
465
|
-
type: "object",
|
|
466
|
-
//required: ["action_javascript_code", "action_name"],
|
|
467
|
-
properties,
|
|
468
|
-
},
|
|
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,
|
|
469
499
|
},
|
|
470
|
-
}
|
|
471
|
-
}
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
|
|
472
503
|
for (const action of config?.actions || []) {
|
|
473
504
|
let properties = {};
|
|
474
505
|
|
|
@@ -532,9 +563,10 @@ ${t.fields
|
|
|
532
563
|
.join(";\n\n") +
|
|
533
564
|
`
|
|
534
565
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
566
|
+
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
|
+
the user is asking for a summary or inference from such rows. The TableQuery query is parametrised by a SQL SELECT query which
|
|
568
|
+
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
|
+
always return porimary key values from the specified table.
|
|
538
570
|
`;
|
|
539
571
|
//console.log("sysprompt", systemPrompt);
|
|
540
572
|
|
|
@@ -575,7 +607,7 @@ const renderQueryInteraction = async (table, result, config, req) => {
|
|
|
575
607
|
if (typeof result === "number")
|
|
576
608
|
return wrapSegment(
|
|
577
609
|
wrapCard(
|
|
578
|
-
"Query " + table
|
|
610
|
+
"Query " + table?.name || "",
|
|
579
611
|
//div("Query: ", code(JSON.stringify(query))),
|
|
580
612
|
`${result}`
|
|
581
613
|
),
|
|
@@ -584,7 +616,7 @@ const renderQueryInteraction = async (table, result, config, req) => {
|
|
|
584
616
|
if (result.length === 0)
|
|
585
617
|
return wrapSegment(
|
|
586
618
|
wrapCard(
|
|
587
|
-
"Query " + table
|
|
619
|
+
"Query " + table?.name || "",
|
|
588
620
|
//div("Query: ", code(JSON.stringify(query))),
|
|
589
621
|
"No rows found"
|
|
590
622
|
),
|
|
@@ -630,6 +662,7 @@ const process_interaction = async (
|
|
|
630
662
|
) => {
|
|
631
663
|
const complArgs = await getCompletionArguments(config);
|
|
632
664
|
complArgs.chat = run.context.interactions;
|
|
665
|
+
//complArgs.debugResult = true;
|
|
633
666
|
//console.log(complArgs);
|
|
634
667
|
console.log("complArgs", JSON.stringify(complArgs, null, 2));
|
|
635
668
|
|
|
@@ -638,12 +671,20 @@ const process_interaction = async (
|
|
|
638
671
|
await addToContext(run, {
|
|
639
672
|
interactions:
|
|
640
673
|
typeof answer === "object" && answer.tool_calls
|
|
641
|
-
? [
|
|
674
|
+
? [
|
|
675
|
+
{
|
|
676
|
+
role: "assistant",
|
|
677
|
+
tool_calls: answer.tool_calls,
|
|
678
|
+
content: answer.content,
|
|
679
|
+
},
|
|
680
|
+
]
|
|
642
681
|
: [{ role: "assistant", content: answer }],
|
|
643
682
|
});
|
|
644
683
|
const responses = [];
|
|
645
684
|
|
|
646
685
|
if (typeof answer === "object" && answer.tool_calls) {
|
|
686
|
+
if (answer.content)
|
|
687
|
+
responses.push(wrapSegment(md.render(answer.content), "Copilot"));
|
|
647
688
|
//const actions = [];
|
|
648
689
|
let hasResult = false;
|
|
649
690
|
for (const tool_call of answer.tool_calls) {
|
|
@@ -702,12 +743,12 @@ const process_interaction = async (
|
|
|
702
743
|
},
|
|
703
744
|
],
|
|
704
745
|
});
|
|
705
|
-
} else if (tool_call.function.name
|
|
746
|
+
} else if (tool_call.function.name == "TableQuery") {
|
|
747
|
+
const query = JSON.parse(tool_call.function.arguments);
|
|
706
748
|
const table = Table.findOne({
|
|
707
|
-
name:
|
|
749
|
+
name: query.table_name,
|
|
708
750
|
});
|
|
709
751
|
const tableCfg = config.tables.find((t) => t.table_name === table.name);
|
|
710
|
-
const query = JSON.parse(tool_call.function.arguments);
|
|
711
752
|
|
|
712
753
|
const is_sqlite = db.isSQLite;
|
|
713
754
|
|