@saltcorn/agents 0.4.6 → 0.4.7

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.
Files changed (3) hide show
  1. package/agent-view.js +27 -3
  2. package/common.js +97 -61
  3. 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,30 @@ 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
+ ensure_script_loaded("/static_assets/${
166
+ db.connectObj.version_tag
167
+ }/socket.io.min.js")
168
+ const collabCfg = {
169
+ events: {
170
+ ['${view.getRealTimeEventName(
171
+ "STREAM_CHUNK"
172
+ )}' + \`?page_load_tag=\${_sc_pageloadtag}\`]: async (data) => {
173
+ $('form.agent-view div.next_response_scratch').append(
174
+ data.content
175
+ );
176
+ }
177
+ }
178
+ };
179
+ setTimeout(() => {
180
+ init_collab_room('${viewname}', collabCfg);
181
+ });`)
182
+ );
183
+ };
184
+
162
185
  const run = async (
163
186
  table_id,
164
187
  viewname,
@@ -388,7 +411,8 @@ const run = async (
388
411
  skill_form_widgets,
389
412
  explainer && small({ class: "explainer" }, i(explainer))
390
413
  ),
391
- stream && div({ class: "next_response_scratch" })
414
+ stream &&
415
+ realTimeCollabScript(viewname) + div({ class: "next_response_scratch" })
392
416
  );
393
417
 
394
418
  const prev_runs_side_bar = div(
@@ -692,7 +716,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
692
716
  action.name,
693
717
  [],
694
718
  triggering_row,
695
- config.stream
719
+ config
696
720
  );
697
721
  };
698
722
 
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
 
@@ -202,8 +203,9 @@ const process_interaction = async (
202
203
  agent_label = "Copilot",
203
204
  prevResponses = [],
204
205
  triggering_row = {},
205
- stream = false
206
+ agentsViewCfg = { stream: false }
206
207
  ) => {
208
+ const { stream, viewname } = agentsViewCfg;
207
209
  const sysState = getState();
208
210
  const complArgs = await getCompletionArguments(
209
211
  config,
@@ -217,21 +219,19 @@ const process_interaction = async (
217
219
  const debugMode = is_debug_mode(config, req.user);
218
220
  const debugCollector = {};
219
221
  if (debugMode) complArgs.debugCollector = debugCollector;
220
- if (stream && sysState.getConfig("enable_dynamic_updates") && req.user) {
222
+ if (stream && viewname) {
221
223
  complArgs.streamCallback = (response) => {
222
224
  const content =
223
- response.choices[0].content || response.choices[0].delta?.content;
224
- if (content)
225
- sysState?.emitDynamicUpdate(
226
- db.getTenantSchema(),
227
- {
228
- eval_js: `$('form.agent-view div.next_response_scratch').append(${JSON.stringify(
229
- content
230
- )})`,
231
- page_load_tag: req.body.page_load_tag,
232
- },
233
- [req.user.id]
234
- );
225
+ typeof response === "string"
226
+ ? response
227
+ : response.choices[0].content || response.choices[0].delta?.content;
228
+ if (content) {
229
+ const view = View.findOne({ name: viewname });
230
+ const pageLoadTag = req.body.page_load_tag;
231
+ view.emitRealTimeEvent(`STREAM_CHUNK?page_load_tag=${pageLoadTag}`, {
232
+ content,
233
+ });
234
+ }
235
235
  };
236
236
  }
237
237
  const answer = await sysState.functions.llm_generate.run("", complArgs);
@@ -274,18 +274,23 @@ const process_interaction = async (
274
274
  if (answer.content && !answer.tool_calls)
275
275
  responses.push(wrapSegment(md.render(answer.content), agent_label));
276
276
  }
277
- await addToContext(run, {
278
- interactions:
279
- typeof answer === "object" && answer.tool_calls
280
- ? [
281
- {
282
- role: "assistant",
283
- tool_calls: answer.tool_calls,
284
- content: answer.content,
285
- },
286
- ]
287
- : [{ role: "assistant", content: answer }],
288
- });
277
+ if (answer.ai_sdk)
278
+ await addToContext(run, {
279
+ interactions: answer.messages,
280
+ });
281
+ else
282
+ await addToContext(run, {
283
+ interactions:
284
+ typeof answer === "object" && answer.tool_calls
285
+ ? [
286
+ {
287
+ role: "assistant",
288
+ tool_calls: answer.tool_calls,
289
+ content: answer.content,
290
+ },
291
+ ]
292
+ : [{ role: "assistant", content: answer }],
293
+ });
289
294
  if (
290
295
  answer &&
291
296
  typeof answer === "object" &&
@@ -297,36 +302,39 @@ const process_interaction = async (
297
302
  let hasResult = false;
298
303
  if ((answer.mcp_calls || []).length && !answer.content) hasResult = true;
299
304
  for (const tool_call of answer.tool_calls || []) {
300
- console.log("call function", tool_call.function?.name);
305
+ console.log(
306
+ "call function",
307
+ tool_call.toolName || tool_call.function?.name
308
+ );
301
309
 
302
310
  await addToContext(run, {
303
- funcalls: { [tool_call.id]: tool_call.function },
311
+ funcalls: {
312
+ [tool_call.id || tool_call.toolCallId]: answer.ai_sdk
313
+ ? tool_call
314
+ : tool_call.function,
315
+ },
304
316
  });
305
317
 
306
- const tool = find_tool(tool_call.function?.name, config);
318
+ const tool = find_tool(
319
+ tool_call.toolName || tool_call.function?.name,
320
+ config
321
+ );
307
322
 
308
323
  if (tool) {
309
- if (
310
- stream &&
311
- sysState.getConfig("enable_dynamic_updates") &&
312
- req.user
313
- ) {
324
+ if (stream && viewname) {
314
325
  let content =
315
326
  "Using skill: " + tool.skill.skill_label ||
316
327
  tool.skill.constructor.skill_name;
317
- sysState?.emitDynamicUpdate(
318
- db.getTenantSchema(),
319
- {
320
- eval_js: `$('form.agent-view div.next_response_scratch').append(${JSON.stringify(
321
- content
322
- )})`,
323
- page_load_tag: req.body.page_load_tag,
324
- },
325
- [req.user.id]
326
- );
328
+ const view = View.findOne({ name: viewname });
329
+ const pageLoadTag = req.body.page_load_tag;
330
+ view.emitRealTimeEvent(`STREAM_CHUNK?page_load_tag=${pageLoadTag}`, {
331
+ content,
332
+ });
327
333
  }
328
334
  if (tool.tool.renderToolCall) {
329
- const row = JSON.parse(tool_call.function.arguments);
335
+ const row = answer.ai_sdk
336
+ ? tool_call.input
337
+ : JSON.parse(tool_call.function.arguments);
330
338
  const rendered = await tool.tool.renderToolCall(row, {
331
339
  req,
332
340
  });
@@ -343,7 +351,9 @@ const process_interaction = async (
343
351
  }
344
352
  hasResult = true;
345
353
  const result = await tool.tool.process(
346
- JSON.parse(tool_call.function.arguments),
354
+ answer.ai_sdk
355
+ ? tool_call.input
356
+ : JSON.parse(tool_call.function.arguments),
347
357
  { req }
348
358
  );
349
359
  if (
@@ -367,20 +377,46 @@ const process_interaction = async (
367
377
  }
368
378
  hasResult = true;
369
379
  }
370
- await addToContext(run, {
371
- interactions: [
372
- {
373
- role: "tool",
374
- tool_call_id: tool_call.id,
375
- call_id: tool_call.call_id,
376
- name: tool_call.function.name,
377
- content:
378
- result && typeof result !== "string"
379
- ? JSON.stringify(result)
380
- : result || "Action run",
381
- },
382
- ],
383
- });
380
+ if (answer.ai_sdk)
381
+ await addToContext(run, {
382
+ interactions: [
383
+ {
384
+ role: "tool",
385
+ content: [
386
+ {
387
+ type: "tool-result",
388
+ toolCallId: tool_call.toolCallId,
389
+ toolName: tool_call.toolName,
390
+ output:
391
+ !result || typeof result === "string"
392
+ ? {
393
+ type: "text",
394
+ value: result || "Action run",
395
+ }
396
+ : {
397
+ type: "json",
398
+ value: JSON.parse(JSON.stringify(result)),
399
+ },
400
+ },
401
+ ],
402
+ },
403
+ ],
404
+ });
405
+ else
406
+ await addToContext(run, {
407
+ interactions: [
408
+ {
409
+ role: "tool",
410
+ tool_call_id: tool_call.toolCallId || tool_call.id,
411
+ call_id: tool_call.call_id,
412
+ name: tool_call.toolName || tool_call.function.name,
413
+ content:
414
+ result && typeof result !== "string"
415
+ ? JSON.stringify(result)
416
+ : result || "Action run",
417
+ },
418
+ ],
419
+ });
384
420
  }
385
421
  }
386
422
  if (hasResult)
@@ -391,7 +427,7 @@ const process_interaction = async (
391
427
  agent_label,
392
428
  [...prevResponses, ...responses],
393
429
  triggering_row,
394
- stream
430
+ agentsViewCfg
395
431
  );
396
432
  } else if (typeof answer === "string")
397
433
  responses.push(wrapSegment(md.render(answer), agent_label));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {