@saltcorn/agents 0.6.0 → 0.6.1

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 +128 -115
  2. package/common.js +4 -1
  3. package/package.json +1 -1
package/agent-view.js CHANGED
@@ -30,6 +30,7 @@ const {
30
30
  textarea,
31
31
  label,
32
32
  a,
33
+ br,
33
34
  } = require("@saltcorn/markup/tags");
34
35
  const { getState } = require("@saltcorn/data/db/state");
35
36
  const {
@@ -265,135 +266,138 @@ const run = async (
265
266
  id: state.run_id,
266
267
  });
267
268
  const interactMarkups = [];
268
- for (const interact of run.context.interactions) {
269
- switch (interact.role) {
270
- case "user":
271
- if (interact.content?.[0]?.type === "image_url") {
272
- const image_url = interact.content[0].image_url.url;
273
- if (image_url.startsWith("data"))
269
+ if (run.context.html_interactions) {
270
+ interactMarkups.push(...run.context.html_interactions);
271
+ } else
272
+ for (const interact of run.context.interactions) {
273
+ switch (interact.role) {
274
+ case "user":
275
+ if (interact.content?.[0]?.type === "image_url") {
276
+ const image_url = interact.content[0].image_url.url;
277
+ if (image_url.startsWith("data"))
278
+ interactMarkups.push(
279
+ div(
280
+ { class: "interaction-segment" },
281
+ span({ class: "badge bg-secondary" }, "You"),
282
+ "File",
283
+ ),
284
+ );
285
+ else
286
+ interactMarkups.push(
287
+ div(
288
+ { class: "interaction-segment" },
289
+ span({ class: "badge bg-secondary" }, "You"),
290
+ a({ href: image_url, target: "_blank" }, "File"),
291
+ ),
292
+ );
293
+ } else
274
294
  interactMarkups.push(
275
295
  div(
276
296
  { class: "interaction-segment" },
277
297
  span({ class: "badge bg-secondary" }, "You"),
278
- "File",
298
+ md.render(interact.content),
279
299
  ),
280
300
  );
281
- else
282
- interactMarkups.push(
283
- div(
284
- { class: "interaction-segment" },
285
- span({ class: "badge bg-secondary" }, "You"),
286
- a({ href: image_url, target: "_blank" }, "File"),
287
- ),
301
+ break;
302
+ case "assistant":
303
+ case "system":
304
+ for (const tool_call of interact.tool_calls || []) {
305
+ const toolSkill = find_tool(
306
+ tool_call.function?.name,
307
+ action.configuration,
288
308
  );
289
- } else
290
- interactMarkups.push(
291
- div(
292
- { class: "interaction-segment" },
293
- span({ class: "badge bg-secondary" }, "You"),
294
- md.render(interact.content),
295
- ),
296
- );
297
- break;
298
- case "assistant":
299
- case "system":
300
- for (const tool_call of interact.tool_calls || []) {
301
- const toolSkill = find_tool(
302
- tool_call.function?.name,
303
- action.configuration,
304
- );
305
- if (toolSkill) {
306
- const row = JSON.parse(tool_call.function.arguments);
307
- if (toolSkill.tool.renderToolCall) {
308
- const rendered = await toolSkill.tool.renderToolCall(row, {
309
- req,
310
- });
311
- if (rendered)
312
- interactMarkups.push(
313
- wrapSegment(
314
- wrapCard(
315
- toolSkill.skill.skill_label ||
316
- toolSkill.skill.constructor.skill_name,
317
- rendered,
309
+ if (toolSkill) {
310
+ const row = JSON.parse(tool_call.function.arguments);
311
+ if (toolSkill.tool.renderToolCall) {
312
+ const rendered = await toolSkill.tool.renderToolCall(row, {
313
+ req,
314
+ });
315
+ if (rendered)
316
+ interactMarkups.push(
317
+ wrapSegment(
318
+ wrapCard(
319
+ toolSkill.skill.skill_label ||
320
+ toolSkill.skill.constructor.skill_name,
321
+ rendered,
322
+ ),
323
+ action.name,
318
324
  ),
319
- action.name,
320
- ),
321
- );
325
+ );
326
+ }
322
327
  }
323
328
  }
324
- }
325
- for (const image_call of interact.content?.image_calls || []) {
326
- const toolSkill = find_image_tool(action.configuration);
327
- if (toolSkill) {
328
- if (toolSkill.tool.renderToolResponse) {
329
- const rendered = await toolSkill.tool.renderToolResponse(
330
- image_call,
331
- {
332
- req,
333
- },
334
- );
329
+ for (const image_call of interact.content?.image_calls || []) {
330
+ const toolSkill = find_image_tool(action.configuration);
331
+ if (toolSkill) {
332
+ if (toolSkill.tool.renderToolResponse) {
333
+ const rendered = await toolSkill.tool.renderToolResponse(
334
+ image_call,
335
+ {
336
+ req,
337
+ },
338
+ );
335
339
 
336
- if (rendered)
337
- interactMarkups.push(
338
- wrapSegment(
339
- wrapCard(
340
- toolSkill.skill.skill_label ||
341
- toolSkill.skill.constructor.skill_name,
342
- rendered,
340
+ if (rendered)
341
+ interactMarkups.push(
342
+ wrapSegment(
343
+ wrapCard(
344
+ toolSkill.skill.skill_label ||
345
+ toolSkill.skill.constructor.skill_name,
346
+ rendered,
347
+ ),
348
+ action.name,
343
349
  ),
344
- action.name,
345
- ),
346
- );
350
+ );
351
+ }
347
352
  }
348
353
  }
349
- }
350
- if (
351
- typeof interact.content === "string" ||
352
- typeof interact.content?.content === "string"
353
- )
354
- interactMarkups.push(
355
- div(
356
- { class: "interaction-segment" },
357
- span({ class: "badge bg-secondary" }, action.name),
358
- typeof interact.content === "string"
359
- ? md.render(interact.content)
360
- : typeof interact.content?.content === "string"
361
- ? md.render(interact.content.content)
362
- : interact.content,
363
- ),
364
- );
365
- break;
366
- case "tool":
367
- if (interact.content !== "Action run") {
368
- let markupContent;
369
- const toolSkill = find_tool(interact.name, action.configuration);
370
- try {
371
- if (toolSkill?.tool?.renderToolResponse)
372
- markupContent = await toolSkill?.tool?.renderToolResponse?.(
373
- JSON.parse(interact.content),
374
- {
375
- req,
376
- },
377
- );
378
- } catch {
379
- markupContent = pre(interact.content);
380
- }
381
- if (markupContent)
354
+ if (
355
+ typeof interact.content === "string" ||
356
+ typeof interact.content?.content === "string"
357
+ )
382
358
  interactMarkups.push(
383
- wrapSegment(
384
- wrapCard(
385
- toolSkill?.skill?.skill_label ||
386
- toolSkill?.skill?.constructor.skill_name ||
387
- interact.name,
388
- markupContent,
389
- ),
390
- action.name,
359
+ div(
360
+ { class: "interaction-segment" },
361
+ span({ class: "badge bg-secondary" }, action.name),
362
+ typeof interact.content === "string"
363
+ ? md.render(interact.content)
364
+ : typeof interact.content?.content === "string"
365
+ ? md.render(interact.content.content)
366
+ : interact.content,
391
367
  ),
392
368
  );
393
- }
394
- break;
369
+ break;
370
+ case "tool":
371
+ if (interact.content !== "Action run") {
372
+ let markupContent;
373
+ const toolSkill = find_tool(interact.name, action.configuration);
374
+ try {
375
+ if (toolSkill?.tool?.renderToolResponse)
376
+ markupContent = await toolSkill?.tool?.renderToolResponse?.(
377
+ JSON.parse(interact.content),
378
+ {
379
+ req,
380
+ },
381
+ );
382
+ } catch {
383
+ markupContent = pre(interact.content);
384
+ }
385
+ if (markupContent)
386
+ interactMarkups.push(
387
+ wrapSegment(
388
+ wrapCard(
389
+ toolSkill?.skill?.skill_label ||
390
+ toolSkill?.skill?.constructor.skill_name ||
391
+ interact.name,
392
+ markupContent,
393
+ ),
394
+ action.name,
395
+ ),
396
+ );
397
+ }
398
+ break;
399
+ }
395
400
  }
396
- }
397
401
  runInteractions = interactMarkups.join("");
398
402
  }
399
403
  const skill_form_widgets = [];
@@ -518,7 +522,9 @@ const run = async (
518
522
 
519
523
  p(
520
524
  { class: "prevrun_content" },
521
- run.context.interactions[0]?.content?.substring?.(0, 80),
525
+ run.context.interactions
526
+ .find((i) => typeof i?.content === "string")
527
+ ?.content?.substring?.(0, 80),
522
528
  ),
523
529
  ),
524
530
  ),
@@ -615,6 +621,7 @@ const run = async (
615
621
  function processCopilotResponse(res) {
616
622
  console.log("processCopilotResponse", res)
617
623
  const hadFile = $("input#attach_agent_image").val();
624
+ let fileBadge = hadFile ? '<span class="badge text-bg-info"><i class="fas fa-image me-1"></i>'+$("input#attach_agent_image")[0].files?.item?.(0)?.name||"File"+'</span>': ""
618
625
  $("span.filename-label").text("");
619
626
  $("input#attach_agent_image").val(null);
620
627
  $("#sendbuttonicon").attr("class","far fa-paper-plane");
@@ -622,9 +629,7 @@ const run = async (
622
629
  if(res.run_id && (!$runidin.val() || $runidin.val()=="undefined"))
623
630
  $runidin.val(res.run_id);
624
631
  const wrapSegment = (html, who) => '<div class="interaction-segment"><span class="badge bg-secondary">'+who+'</span>'+html+'</div>'
625
- $("#copilotinteractions").append(wrapSegment('<p>'+$("textarea[name=userinput]").val()+'</p>', "You"))
626
- if(hadFile)
627
- $("#copilotinteractions").append(wrapSegment('File', "You"))
632
+ $("#copilotinteractions").append(wrapSegment('<p>'+$("textarea[name=userinput]").val()+'</p>'+fileBadge, "You"))
628
633
  $("textarea[name=userinput]").val("")
629
634
  $('form.agent-view div.next_response_scratch').html("")
630
635
  window['stream scratch ${viewname} ${rndid}'] = []
@@ -736,6 +741,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
736
741
  context: {
737
742
  implemented_fcall_ids: [],
738
743
  interactions: [...ini_interacts],
744
+ html_interactions: [],
739
745
  funcalls: {},
740
746
  triggering_row_id,
741
747
  },
@@ -743,6 +749,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
743
749
  } else {
744
750
  run = await WorkflowRun.findOne({ id: +run_id });
745
751
  }
752
+ let fileBadges = "";
746
753
  if (config.image_upload && req.files?.file) {
747
754
  const file = await File.from_req_files(
748
755
  req.files.file,
@@ -750,6 +757,11 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
750
757
  100,
751
758
  // file_field?.attributes?.folder
752
759
  );
760
+ fileBadges = span(
761
+ { class: "badge text-bg-info" },
762
+ i({ class: "fas fa-image me-1" }),
763
+ file.filename,
764
+ );
753
765
  const baseUrl = getState().getConfig("base_url").replace(/\/$/, "");
754
766
  let imageurl;
755
767
  if (
@@ -774,6 +786,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
774
786
  ...(run.context.interactions || []),
775
787
  { role: "user", content: userinput },
776
788
  ],
789
+ html_interactions: [wrapSegment(p(userinput) + fileBadges, "You")],
777
790
  });
778
791
  const dyn_updates = getState().getConfig("enable_dynamic_updates", true);
779
792
  const process_promise = process_interaction(
package/common.js CHANGED
@@ -236,7 +236,7 @@ const process_interaction = async (
236
236
  interactions: complArgs.chat,
237
237
  });
238
238
  const responses = [];
239
- const add_response = (resp) => {
239
+ const add_response = async (resp) => {
240
240
  if (dyn_updates)
241
241
  getState().emitDynamicUpdate(
242
242
  db.getTenantSchema(),
@@ -246,6 +246,9 @@ const process_interaction = async (
246
246
  [req.user.id],
247
247
  );
248
248
  else responses.push(resp);
249
+ await addToContext(run, {
250
+ html_interactions: [resp],
251
+ });
249
252
  };
250
253
  if (answer && typeof answer === "object" && answer.image_calls) {
251
254
  for (const image_call of answer.image_calls) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {