@saltcorn/agents 0.4.2 → 0.4.4
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-view.js +13 -3
- package/common.js +46 -12
- package/index.js +6 -1
- package/package.json +3 -2
- package/skills/PreloadData.js +2 -0
package/agent-view.js
CHANGED
|
@@ -86,6 +86,12 @@ const configuration_workflow = (req) =>
|
|
|
86
86
|
name: "prev_runs_closed",
|
|
87
87
|
label: "Initially closed",
|
|
88
88
|
type: "Bool",
|
|
89
|
+
showIf: { show_prev_runs: true },
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "stream",
|
|
93
|
+
label: "Stream response",
|
|
94
|
+
type: "Bool",
|
|
89
95
|
},
|
|
90
96
|
{
|
|
91
97
|
name: "placeholder",
|
|
@@ -161,6 +167,7 @@ const run = async (
|
|
|
161
167
|
placeholder,
|
|
162
168
|
explainer,
|
|
163
169
|
image_upload,
|
|
170
|
+
stream,
|
|
164
171
|
},
|
|
165
172
|
state,
|
|
166
173
|
{ res, req }
|
|
@@ -320,7 +327,7 @@ const run = async (
|
|
|
320
327
|
const input_form = form(
|
|
321
328
|
{
|
|
322
329
|
onsubmit: `event.preventDefault();spin_send_button();view_post('${viewname}', 'interact', new FormData(this), processCopilotResponse);return false;`,
|
|
323
|
-
class: "form-namespace copilot mt-2",
|
|
330
|
+
class: ["form-namespace copilot mt-2 agent-view"],
|
|
324
331
|
method: "post",
|
|
325
332
|
},
|
|
326
333
|
input({
|
|
@@ -365,7 +372,8 @@ const run = async (
|
|
|
365
372
|
class: "debugicon fas fa-bug",
|
|
366
373
|
}),
|
|
367
374
|
explainer && small({ class: "explainer" }, i(explainer))
|
|
368
|
-
)
|
|
375
|
+
),
|
|
376
|
+
stream && div({ class: "next_response_scratch" })
|
|
369
377
|
);
|
|
370
378
|
|
|
371
379
|
const prev_runs_side_bar = div(
|
|
@@ -497,6 +505,7 @@ const run = async (
|
|
|
497
505
|
if(hadFile)
|
|
498
506
|
$("#copilotinteractions").append(wrapSegment('File', "You"))
|
|
499
507
|
$("textarea[name=userinput]").val("")
|
|
508
|
+
$('form.agent-view div.next_response_scratch').html("")
|
|
500
509
|
|
|
501
510
|
if(res.response)
|
|
502
511
|
$("#copilotinteractions").append(res.response)
|
|
@@ -657,7 +666,8 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
657
666
|
req,
|
|
658
667
|
action.name,
|
|
659
668
|
[],
|
|
660
|
-
triggering_row
|
|
669
|
+
triggering_row,
|
|
670
|
+
config.stream
|
|
661
671
|
);
|
|
662
672
|
};
|
|
663
673
|
|
package/common.js
CHANGED
|
@@ -2,6 +2,7 @@ const { getState } = require("@saltcorn/data/db/state");
|
|
|
2
2
|
const { div, span } = require("@saltcorn/markup/tags");
|
|
3
3
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
4
4
|
const { interpolate } = require("@saltcorn/data/utils");
|
|
5
|
+
const db = require("@saltcorn/data/db");
|
|
5
6
|
|
|
6
7
|
const MarkdownIt = require("markdown-it"),
|
|
7
8
|
md = new MarkdownIt();
|
|
@@ -105,13 +106,9 @@ const getCompletionArguments = async (config, user, triggering_row) => {
|
|
|
105
106
|
else if (skillTools) tools.push(skillTools);
|
|
106
107
|
}
|
|
107
108
|
if (tools.length === 0) tools = undefined;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const getCompletion = async (language, prompt) => {
|
|
112
|
-
return getState().functions.llm_generate.run(prompt, {
|
|
113
|
-
systemPrompt: `You are a helpful code assistant. Your language of choice is ${language}. Do not include any explanation, just generate the code block itself.`,
|
|
114
|
-
});
|
|
109
|
+
const complArgs = { tools, systemPrompt: sysPrompts.join("\n\n") };
|
|
110
|
+
if (config.model) complArgs.model = config.model;
|
|
111
|
+
return complArgs;
|
|
115
112
|
};
|
|
116
113
|
|
|
117
114
|
const incompleteCfgMsg = () => {
|
|
@@ -194,8 +191,10 @@ const process_interaction = async (
|
|
|
194
191
|
req,
|
|
195
192
|
agent_label = "Copilot",
|
|
196
193
|
prevResponses = [],
|
|
197
|
-
triggering_row = {}
|
|
194
|
+
triggering_row = {},
|
|
195
|
+
stream = false
|
|
198
196
|
) => {
|
|
197
|
+
const sysState = getState();
|
|
199
198
|
const complArgs = await getCompletionArguments(
|
|
200
199
|
config,
|
|
201
200
|
req.user,
|
|
@@ -207,7 +206,24 @@ const process_interaction = async (
|
|
|
207
206
|
const debugMode = is_debug_mode(config, req.user);
|
|
208
207
|
const debugCollector = {};
|
|
209
208
|
if (debugMode) complArgs.debugCollector = debugCollector;
|
|
210
|
-
|
|
209
|
+
if (stream && sysState.getConfig("enable_dynamic_updates") && req.user) {
|
|
210
|
+
complArgs.streamCallback = (response) => {
|
|
211
|
+
const content =
|
|
212
|
+
response.choices[0].content || response.choices[0].delta?.content;
|
|
213
|
+
if (content)
|
|
214
|
+
sysState?.emitDynamicUpdate(
|
|
215
|
+
db.getTenantSchema(),
|
|
216
|
+
{
|
|
217
|
+
eval_js: `$('form.agent-view div.next_response_scratch').append(${JSON.stringify(
|
|
218
|
+
content
|
|
219
|
+
)})`,
|
|
220
|
+
},
|
|
221
|
+
[req.user.id]
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
const answer = await sysState.functions.llm_generate.run("", complArgs);
|
|
226
|
+
|
|
211
227
|
if (debugMode)
|
|
212
228
|
await addToContext(run, {
|
|
213
229
|
api_interactions: [debugCollector],
|
|
@@ -267,7 +283,7 @@ const process_interaction = async (
|
|
|
267
283
|
let hasResult = false;
|
|
268
284
|
if ((answer.mcp_calls || []).length && !answer.content) hasResult = true;
|
|
269
285
|
for (const tool_call of answer.tool_calls || []) {
|
|
270
|
-
console.log("call function", tool_call.function);
|
|
286
|
+
console.log("call function", tool_call.function?.name);
|
|
271
287
|
|
|
272
288
|
await addToContext(run, {
|
|
273
289
|
funcalls: { [tool_call.id]: tool_call.function },
|
|
@@ -276,6 +292,24 @@ const process_interaction = async (
|
|
|
276
292
|
const tool = find_tool(tool_call.function?.name, config);
|
|
277
293
|
|
|
278
294
|
if (tool) {
|
|
295
|
+
if (
|
|
296
|
+
stream &&
|
|
297
|
+
sysState.getConfig("enable_dynamic_updates") &&
|
|
298
|
+
req.user
|
|
299
|
+
) {
|
|
300
|
+
let content =
|
|
301
|
+
"Using skill: " + tool.skill.skill_label ||
|
|
302
|
+
tool.skill.constructor.skill_name;
|
|
303
|
+
sysState?.emitDynamicUpdate(
|
|
304
|
+
db.getTenantSchema(),
|
|
305
|
+
{
|
|
306
|
+
eval_js: `$('form.agent-view div.next_response_scratch').append(${JSON.stringify(
|
|
307
|
+
content
|
|
308
|
+
)})`,
|
|
309
|
+
},
|
|
310
|
+
[req.user.id]
|
|
311
|
+
);
|
|
312
|
+
}
|
|
279
313
|
if (tool.tool.renderToolCall) {
|
|
280
314
|
const row = JSON.parse(tool_call.function.arguments);
|
|
281
315
|
const rendered = await tool.tool.renderToolCall(row, {
|
|
@@ -341,7 +375,8 @@ const process_interaction = async (
|
|
|
341
375
|
req,
|
|
342
376
|
agent_label,
|
|
343
377
|
[...prevResponses, ...responses],
|
|
344
|
-
triggering_row
|
|
378
|
+
triggering_row,
|
|
379
|
+
stream
|
|
345
380
|
);
|
|
346
381
|
} else if (typeof answer === "string")
|
|
347
382
|
responses.push(wrapSegment(md.render(answer), agent_label));
|
|
@@ -359,7 +394,6 @@ module.exports = {
|
|
|
359
394
|
get_skills,
|
|
360
395
|
get_skill_class,
|
|
361
396
|
incompleteCfgMsg,
|
|
362
|
-
getCompletion,
|
|
363
397
|
find_tool,
|
|
364
398
|
get_skill_instances,
|
|
365
399
|
getCompletionArguments,
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/agents",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "AI agents for Saltcorn",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"node-sql-parser": "4.15.0",
|
|
10
10
|
"markdown-it": "14.1.0",
|
|
11
11
|
"style-to-object": "1.0.8",
|
|
12
|
-
"node-html-parser": "7.0.1"
|
|
12
|
+
"node-html-parser": "7.0.1",
|
|
13
|
+
"node-fetch": "2.6.9"
|
|
13
14
|
},
|
|
14
15
|
"author": "Tom Nielsen",
|
|
15
16
|
"license": "MIT",
|
package/skills/PreloadData.js
CHANGED
|
@@ -11,6 +11,7 @@ const db = require("@saltcorn/data/db");
|
|
|
11
11
|
const { eval_expression } = require("@saltcorn/data/models/expression");
|
|
12
12
|
const { interpolate } = require("@saltcorn/data/utils");
|
|
13
13
|
const vm = require("vm");
|
|
14
|
+
const fetch = global.fetch || require("node-fetch");
|
|
14
15
|
|
|
15
16
|
class PreloadData {
|
|
16
17
|
static skill_name = "Preload Data";
|
|
@@ -36,6 +37,7 @@ class PreloadData {
|
|
|
36
37
|
Trigger,
|
|
37
38
|
setTimeout,
|
|
38
39
|
interpolate,
|
|
40
|
+
fetch,
|
|
39
41
|
require,
|
|
40
42
|
getConfig: (k) =>
|
|
41
43
|
sysState.isFixedConfig(k) ? undefined : sysState.getConfig(k),
|