@saltcorn/agents 0.4.5 → 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 +45 -12
  2. package/common.js +97 -59
  3. package/package.json +1 -1
package/agent-view.js CHANGED
@@ -158,6 +158,30 @@ const uploadForm = (viewname, req) =>
158
158
  span({ class: "ms-2 filename-label" })
159
159
  );
160
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
+
161
185
  const run = async (
162
186
  table_id,
163
187
  viewname,
@@ -346,10 +370,14 @@ const run = async (
346
370
  }),
347
371
  input({
348
372
  type: "hidden",
349
- class: "form-control ",
350
373
  name: "run_id",
351
374
  value: state.run_id ? +state.run_id : undefined,
352
375
  }),
376
+ input({
377
+ type: "hidden",
378
+ name: "page_load_tag",
379
+ value: "",
380
+ }),
353
381
  input({
354
382
  type: "hidden",
355
383
  class: "form-control ",
@@ -383,7 +411,8 @@ const run = async (
383
411
  skill_form_widgets,
384
412
  explainer && small({ class: "explainer" }, i(explainer))
385
413
  ),
386
- stream && div({ class: "next_response_scratch" })
414
+ stream &&
415
+ realTimeCollabScript(viewname) + div({ class: "next_response_scratch" })
387
416
  );
388
417
 
389
418
  const prev_runs_side_bar = div(
@@ -500,15 +529,15 @@ const run = async (
500
529
  ),
501
530
  script(
502
531
  `
503
- function close_session_list() {
504
- $("div.prev-runs-list").hide().parents(".col-3").removeClass("col-3").addClass("was-col-3").parent().children(".col-9").removeClass("col-9").addClass("col-12")
505
- $("div.open-prev-runs").show()
506
- }
507
- function open_session_list() {
508
- $("div.prev-runs-list").show().parents(".was-col-3").removeClass(["was-col-3","col-0","d-none"]).addClass("col-3").parent().children(".col-12").removeClass("col-12").addClass("col-9")
509
- $("div.open-prev-runs").hide()
510
- }
511
- function processCopilotResponse(res) {
532
+ function close_session_list() {
533
+ $("div.prev-runs-list").hide().parents(".col-3").removeClass("col-3").addClass("was-col-3").parent().children(".col-9").removeClass("col-9").addClass("col-12")
534
+ $("div.open-prev-runs").show()
535
+ }
536
+ function open_session_list() {
537
+ $("div.prev-runs-list").show().parents(".was-col-3").removeClass(["was-col-3","col-0","d-none"]).addClass("col-3").parent().children(".col-12").removeClass("col-12").addClass("col-9")
538
+ $("div.open-prev-runs").hide()
539
+ }
540
+ function processCopilotResponse(res) {
512
541
  const hadFile = $("input#attach_agent_image").val();
513
542
  $("span.filename-label").text("");
514
543
  $("input#attach_agent_image").val(null);
@@ -582,6 +611,10 @@ const run = async (
582
611
  function spin_send_button() {
583
612
  $("#sendbuttonicon").attr("class","fas fa-spinner fa-spin");
584
613
  };`,
614
+ stream &&
615
+ domReady(
616
+ `$('form.agent-view input[name=page_load_tag]').val(window._sc_pageloadtag)`
617
+ ),
585
618
  initial_q && domReady("$('form.copilot').submit()")
586
619
  )
587
620
  )
@@ -683,7 +716,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
683
716
  action.name,
684
717
  [],
685
718
  triggering_row,
686
- config.stream
719
+ config
687
720
  );
688
721
  };
689
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,20 +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
- },
232
- [req.user.id]
233
- );
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
+ }
234
235
  };
235
236
  }
236
237
  const answer = await sysState.functions.llm_generate.run("", complArgs);
@@ -273,18 +274,23 @@ const process_interaction = async (
273
274
  if (answer.content && !answer.tool_calls)
274
275
  responses.push(wrapSegment(md.render(answer.content), agent_label));
275
276
  }
276
- await addToContext(run, {
277
- interactions:
278
- typeof answer === "object" && answer.tool_calls
279
- ? [
280
- {
281
- role: "assistant",
282
- tool_calls: answer.tool_calls,
283
- content: answer.content,
284
- },
285
- ]
286
- : [{ role: "assistant", content: answer }],
287
- });
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
+ });
288
294
  if (
289
295
  answer &&
290
296
  typeof answer === "object" &&
@@ -296,35 +302,39 @@ const process_interaction = async (
296
302
  let hasResult = false;
297
303
  if ((answer.mcp_calls || []).length && !answer.content) hasResult = true;
298
304
  for (const tool_call of answer.tool_calls || []) {
299
- console.log("call function", tool_call.function?.name);
305
+ console.log(
306
+ "call function",
307
+ tool_call.toolName || tool_call.function?.name
308
+ );
300
309
 
301
310
  await addToContext(run, {
302
- 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
+ },
303
316
  });
304
317
 
305
- 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
+ );
306
322
 
307
323
  if (tool) {
308
- if (
309
- stream &&
310
- sysState.getConfig("enable_dynamic_updates") &&
311
- req.user
312
- ) {
324
+ if (stream && viewname) {
313
325
  let content =
314
326
  "Using skill: " + tool.skill.skill_label ||
315
327
  tool.skill.constructor.skill_name;
316
- sysState?.emitDynamicUpdate(
317
- db.getTenantSchema(),
318
- {
319
- eval_js: `$('form.agent-view div.next_response_scratch').append(${JSON.stringify(
320
- content
321
- )})`,
322
- },
323
- [req.user.id]
324
- );
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
+ });
325
333
  }
326
334
  if (tool.tool.renderToolCall) {
327
- 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);
328
338
  const rendered = await tool.tool.renderToolCall(row, {
329
339
  req,
330
340
  });
@@ -341,7 +351,9 @@ const process_interaction = async (
341
351
  }
342
352
  hasResult = true;
343
353
  const result = await tool.tool.process(
344
- JSON.parse(tool_call.function.arguments),
354
+ answer.ai_sdk
355
+ ? tool_call.input
356
+ : JSON.parse(tool_call.function.arguments),
345
357
  { req }
346
358
  );
347
359
  if (
@@ -365,20 +377,46 @@ const process_interaction = async (
365
377
  }
366
378
  hasResult = true;
367
379
  }
368
- await addToContext(run, {
369
- interactions: [
370
- {
371
- role: "tool",
372
- tool_call_id: tool_call.id,
373
- call_id: tool_call.call_id,
374
- name: tool_call.function.name,
375
- content:
376
- result && typeof result !== "string"
377
- ? JSON.stringify(result)
378
- : result || "Action run",
379
- },
380
- ],
381
- });
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
+ });
382
420
  }
383
421
  }
384
422
  if (hasResult)
@@ -389,7 +427,7 @@ const process_interaction = async (
389
427
  agent_label,
390
428
  [...prevResponses, ...responses],
391
429
  triggering_row,
392
- stream
430
+ agentsViewCfg
393
431
  );
394
432
  } else if (typeof answer === "string")
395
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.5",
3
+ "version": "0.4.7",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {