@saltcorn/agents 0.4.6 → 0.4.8
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 +42 -3
- package/common.js +119 -69
- package/index.js +35 -1
- package/package.json +1 -1
package/agent-view.js
CHANGED
|
@@ -93,7 +93,6 @@ const configuration_workflow = (req) =>
|
|
|
93
93
|
name: "stream",
|
|
94
94
|
label: "Stream response",
|
|
95
95
|
type: "Bool",
|
|
96
|
-
sublabel: "Requires dynamic update (Event settings)",
|
|
97
96
|
},
|
|
98
97
|
{
|
|
99
98
|
name: "placeholder",
|
|
@@ -159,6 +158,45 @@ const uploadForm = (viewname, req) =>
|
|
|
159
158
|
span({ class: "ms-2 filename-label" })
|
|
160
159
|
);
|
|
161
160
|
|
|
161
|
+
const realTimeCollabScript = (viewname) => {
|
|
162
|
+
const view = View.findOne({ name: viewname });
|
|
163
|
+
return script(
|
|
164
|
+
domReady(`
|
|
165
|
+
const callback = () => {
|
|
166
|
+
const collabCfg = {
|
|
167
|
+
events: {
|
|
168
|
+
['${view.getRealTimeEventName(
|
|
169
|
+
"STREAM_CHUNK"
|
|
170
|
+
)}' + \`?page_load_tag=\${_sc_pageloadtag}\`]: async (data) => {
|
|
171
|
+
$('form.agent-view div.next_response_scratch').append(
|
|
172
|
+
data.content
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
let retries = 0
|
|
178
|
+
function init_it() {
|
|
179
|
+
if(window.io) init_collab_room('${viewname}', collabCfg);
|
|
180
|
+
else setTimeout(init_it, retries * 100);
|
|
181
|
+
retries+=1;
|
|
182
|
+
}
|
|
183
|
+
init_it();
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
if (ensure_script_loaded.length >= 2) {
|
|
187
|
+
ensure_script_loaded("/static_assets/${
|
|
188
|
+
db.connectObj.version_tag
|
|
189
|
+
}/socket.io.min.js", callback);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
ensure_script_loaded("/static_assets/${
|
|
193
|
+
db.connectObj.version_tag
|
|
194
|
+
}/socket.io.min.js");
|
|
195
|
+
callback();
|
|
196
|
+
}`)
|
|
197
|
+
);
|
|
198
|
+
};
|
|
199
|
+
|
|
162
200
|
const run = async (
|
|
163
201
|
table_id,
|
|
164
202
|
viewname,
|
|
@@ -388,7 +426,8 @@ const run = async (
|
|
|
388
426
|
skill_form_widgets,
|
|
389
427
|
explainer && small({ class: "explainer" }, i(explainer))
|
|
390
428
|
),
|
|
391
|
-
stream &&
|
|
429
|
+
stream &&
|
|
430
|
+
realTimeCollabScript(viewname) + div({ class: "next_response_scratch" })
|
|
392
431
|
);
|
|
393
432
|
|
|
394
433
|
const prev_runs_side_bar = div(
|
|
@@ -692,7 +731,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
|
|
|
692
731
|
action.name,
|
|
693
732
|
[],
|
|
694
733
|
triggering_row,
|
|
695
|
-
config
|
|
734
|
+
config
|
|
696
735
|
);
|
|
697
736
|
};
|
|
698
737
|
|
package/common.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
const View = require("@saltcorn/data/models/view");
|
|
4
5
|
const { interpolate } = require("@saltcorn/data/utils");
|
|
5
6
|
const db = require("@saltcorn/data/db");
|
|
6
7
|
|
|
@@ -163,11 +164,13 @@ const addToContext = async (run, newCtx) => {
|
|
|
163
164
|
};
|
|
164
165
|
|
|
165
166
|
const wrapSegment = (html, who) =>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
who === null
|
|
168
|
+
? html
|
|
169
|
+
: '<div class="interaction-segment"><span class="badge bg-secondary">' +
|
|
170
|
+
who +
|
|
171
|
+
"</span>" +
|
|
172
|
+
html +
|
|
173
|
+
"</div>";
|
|
171
174
|
|
|
172
175
|
const wrapCard = (title, ...inners) =>
|
|
173
176
|
span({ class: "badge bg-info ms-1" }, title) +
|
|
@@ -202,8 +205,9 @@ const process_interaction = async (
|
|
|
202
205
|
agent_label = "Copilot",
|
|
203
206
|
prevResponses = [],
|
|
204
207
|
triggering_row = {},
|
|
205
|
-
|
|
208
|
+
agentsViewCfg = { stream: false }
|
|
206
209
|
) => {
|
|
210
|
+
const { stream, viewname } = agentsViewCfg;
|
|
207
211
|
const sysState = getState();
|
|
208
212
|
const complArgs = await getCompletionArguments(
|
|
209
213
|
config,
|
|
@@ -217,21 +221,19 @@ const process_interaction = async (
|
|
|
217
221
|
const debugMode = is_debug_mode(config, req.user);
|
|
218
222
|
const debugCollector = {};
|
|
219
223
|
if (debugMode) complArgs.debugCollector = debugCollector;
|
|
220
|
-
if (stream &&
|
|
224
|
+
if (stream && viewname) {
|
|
225
|
+
const view = View.findOne({ name: viewname });
|
|
221
226
|
complArgs.streamCallback = (response) => {
|
|
222
227
|
const content =
|
|
223
|
-
response
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
},
|
|
233
|
-
[req.user.id]
|
|
234
|
-
);
|
|
228
|
+
typeof response === "string"
|
|
229
|
+
? response
|
|
230
|
+
: response.choices[0].content || response.choices[0].delta?.content;
|
|
231
|
+
if (content) {
|
|
232
|
+
const pageLoadTag = req.body.page_load_tag;
|
|
233
|
+
view.emitRealTimeEvent(`STREAM_CHUNK?page_load_tag=${pageLoadTag}`, {
|
|
234
|
+
content,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
235
237
|
};
|
|
236
238
|
}
|
|
237
239
|
const answer = await sysState.functions.llm_generate.run("", complArgs);
|
|
@@ -272,61 +274,77 @@ const process_interaction = async (
|
|
|
272
274
|
}
|
|
273
275
|
}
|
|
274
276
|
if (answer.content && !answer.tool_calls)
|
|
275
|
-
responses.push(
|
|
277
|
+
responses.push(
|
|
278
|
+
req.disable_markdown_render
|
|
279
|
+
? answer
|
|
280
|
+
: wrapSegment(md.render(answer.content), agent_label)
|
|
281
|
+
);
|
|
276
282
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
if (answer.ai_sdk)
|
|
284
|
+
await addToContext(run, {
|
|
285
|
+
interactions: answer.messages,
|
|
286
|
+
});
|
|
287
|
+
else
|
|
288
|
+
await addToContext(run, {
|
|
289
|
+
interactions:
|
|
290
|
+
typeof answer === "object" && answer.tool_calls
|
|
291
|
+
? [
|
|
292
|
+
{
|
|
293
|
+
role: "assistant",
|
|
294
|
+
tool_calls: answer.tool_calls,
|
|
295
|
+
content: answer.content,
|
|
296
|
+
},
|
|
297
|
+
]
|
|
298
|
+
: [{ role: "assistant", content: answer }],
|
|
299
|
+
});
|
|
289
300
|
if (
|
|
290
301
|
answer &&
|
|
291
302
|
typeof answer === "object" &&
|
|
292
303
|
(answer.tool_calls || answer.mcp_calls)
|
|
293
304
|
) {
|
|
294
305
|
if (answer.content)
|
|
295
|
-
responses.push(
|
|
306
|
+
responses.push(
|
|
307
|
+
req.disable_markdown_render
|
|
308
|
+
? answer
|
|
309
|
+
: wrapSegment(md.render(answer.content), agent_label)
|
|
310
|
+
);
|
|
296
311
|
//const actions = [];
|
|
297
312
|
let hasResult = false;
|
|
298
313
|
if ((answer.mcp_calls || []).length && !answer.content) hasResult = true;
|
|
299
314
|
for (const tool_call of answer.tool_calls || []) {
|
|
300
|
-
console.log(
|
|
315
|
+
console.log(
|
|
316
|
+
"call function",
|
|
317
|
+
tool_call.toolName || tool_call.function?.name
|
|
318
|
+
);
|
|
301
319
|
|
|
302
320
|
await addToContext(run, {
|
|
303
|
-
funcalls: {
|
|
321
|
+
funcalls: {
|
|
322
|
+
[tool_call.id || tool_call.toolCallId]: answer.ai_sdk
|
|
323
|
+
? tool_call
|
|
324
|
+
: tool_call.function,
|
|
325
|
+
},
|
|
304
326
|
});
|
|
305
327
|
|
|
306
|
-
const tool = find_tool(
|
|
328
|
+
const tool = find_tool(
|
|
329
|
+
tool_call.toolName || tool_call.function?.name,
|
|
330
|
+
config
|
|
331
|
+
);
|
|
307
332
|
|
|
308
333
|
if (tool) {
|
|
309
|
-
if (
|
|
310
|
-
stream &&
|
|
311
|
-
sysState.getConfig("enable_dynamic_updates") &&
|
|
312
|
-
req.user
|
|
313
|
-
) {
|
|
334
|
+
if (stream && viewname) {
|
|
314
335
|
let content =
|
|
315
336
|
"Using skill: " + tool.skill.skill_label ||
|
|
316
337
|
tool.skill.constructor.skill_name;
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
)})`,
|
|
323
|
-
page_load_tag: req.body.page_load_tag,
|
|
324
|
-
},
|
|
325
|
-
[req.user.id]
|
|
326
|
-
);
|
|
338
|
+
const view = View.findOne({ name: viewname });
|
|
339
|
+
const pageLoadTag = req.body.page_load_tag;
|
|
340
|
+
view.emitRealTimeEvent(`STREAM_CHUNK?page_load_tag=${pageLoadTag}`, {
|
|
341
|
+
content,
|
|
342
|
+
});
|
|
327
343
|
}
|
|
328
344
|
if (tool.tool.renderToolCall) {
|
|
329
|
-
const row =
|
|
345
|
+
const row = answer.ai_sdk
|
|
346
|
+
? tool_call.input
|
|
347
|
+
: JSON.parse(tool_call.function.arguments);
|
|
330
348
|
const rendered = await tool.tool.renderToolCall(row, {
|
|
331
349
|
req,
|
|
332
350
|
});
|
|
@@ -343,7 +361,9 @@ const process_interaction = async (
|
|
|
343
361
|
}
|
|
344
362
|
hasResult = true;
|
|
345
363
|
const result = await tool.tool.process(
|
|
346
|
-
|
|
364
|
+
answer.ai_sdk
|
|
365
|
+
? tool_call.input
|
|
366
|
+
: JSON.parse(tool_call.function.arguments),
|
|
347
367
|
{ req }
|
|
348
368
|
);
|
|
349
369
|
if (
|
|
@@ -367,20 +387,46 @@ const process_interaction = async (
|
|
|
367
387
|
}
|
|
368
388
|
hasResult = true;
|
|
369
389
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
390
|
+
if (answer.ai_sdk)
|
|
391
|
+
await addToContext(run, {
|
|
392
|
+
interactions: [
|
|
393
|
+
{
|
|
394
|
+
role: "tool",
|
|
395
|
+
content: [
|
|
396
|
+
{
|
|
397
|
+
type: "tool-result",
|
|
398
|
+
toolCallId: tool_call.toolCallId,
|
|
399
|
+
toolName: tool_call.toolName,
|
|
400
|
+
output:
|
|
401
|
+
!result || typeof result === "string"
|
|
402
|
+
? {
|
|
403
|
+
type: "text",
|
|
404
|
+
value: result || "Action run",
|
|
405
|
+
}
|
|
406
|
+
: {
|
|
407
|
+
type: "json",
|
|
408
|
+
value: JSON.parse(JSON.stringify(result)),
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
},
|
|
413
|
+
],
|
|
414
|
+
});
|
|
415
|
+
else
|
|
416
|
+
await addToContext(run, {
|
|
417
|
+
interactions: [
|
|
418
|
+
{
|
|
419
|
+
role: "tool",
|
|
420
|
+
tool_call_id: tool_call.toolCallId || tool_call.id,
|
|
421
|
+
call_id: tool_call.call_id,
|
|
422
|
+
name: tool_call.toolName || tool_call.function.name,
|
|
423
|
+
content:
|
|
424
|
+
result && typeof result !== "string"
|
|
425
|
+
? JSON.stringify(result)
|
|
426
|
+
: result || "Action run",
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
});
|
|
384
430
|
}
|
|
385
431
|
}
|
|
386
432
|
if (hasResult)
|
|
@@ -391,10 +437,14 @@ const process_interaction = async (
|
|
|
391
437
|
agent_label,
|
|
392
438
|
[...prevResponses, ...responses],
|
|
393
439
|
triggering_row,
|
|
394
|
-
|
|
440
|
+
agentsViewCfg
|
|
395
441
|
);
|
|
396
442
|
} else if (typeof answer === "string")
|
|
397
|
-
responses.push(
|
|
443
|
+
responses.push(
|
|
444
|
+
req.disable_markdown_render
|
|
445
|
+
? answer
|
|
446
|
+
: wrapSegment(md.render(answer), agent_label)
|
|
447
|
+
);
|
|
398
448
|
|
|
399
449
|
return {
|
|
400
450
|
json: {
|
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const Workflow = require("@saltcorn/data/models/workflow");
|
|
2
2
|
const Form = require("@saltcorn/data/models/form");
|
|
3
3
|
const FieldRepeat = require("@saltcorn/data/models/fieldrepeat");
|
|
4
|
-
const
|
|
4
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
5
5
|
const {
|
|
6
6
|
get_skills,
|
|
7
7
|
getCompletionArguments,
|
|
@@ -101,6 +101,40 @@ module.exports = {
|
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
103
|
},
|
|
104
|
+
functions: {
|
|
105
|
+
agent_generate: {
|
|
106
|
+
run: async (agent_name, prompt, opts = {}) => {
|
|
107
|
+
const action = await Trigger.findOne({ name: agent_name });
|
|
108
|
+
const run = await WorkflowRun.create({
|
|
109
|
+
status: "Running",
|
|
110
|
+
started_by: opts.user?.id,
|
|
111
|
+
trigger_id: action.id,
|
|
112
|
+
context: {
|
|
113
|
+
implemented_fcall_ids: [],
|
|
114
|
+
interactions: [{ role: "user", content: prompt }],
|
|
115
|
+
funcalls: {},
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const result = await process_interaction(
|
|
119
|
+
run,
|
|
120
|
+
action.configuration,
|
|
121
|
+
{
|
|
122
|
+
user: opts?.user,
|
|
123
|
+
body: {},
|
|
124
|
+
disable_markdown: opts?.disable_markdown_render
|
|
125
|
+
},
|
|
126
|
+
null
|
|
127
|
+
);
|
|
128
|
+
return result.json.response;
|
|
129
|
+
},
|
|
130
|
+
isAsync: true,
|
|
131
|
+
description: "Run an agent on a prompt",
|
|
132
|
+
arguments: [
|
|
133
|
+
{ name: "agent_name", type: "String" },
|
|
134
|
+
{ name: "prompt", type: "String" },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
104
138
|
};
|
|
105
139
|
|
|
106
140
|
/*
|