@saltcorn/agents 0.3.6 → 0.4.0

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 CHANGED
@@ -114,7 +114,16 @@ const configuration_workflow = (req) =>
114
114
  ],
115
115
  });
116
116
 
117
- const get_state_fields = () => [];
117
+ const get_state_fields = async (table_id) =>
118
+ table_id
119
+ ? [
120
+ {
121
+ name: "id",
122
+ type: "Integer",
123
+ primary_key: true,
124
+ },
125
+ ]
126
+ : [];
118
127
 
119
128
  const uploadForm = (viewname, req) =>
120
129
  span(
@@ -154,6 +163,14 @@ const run = async (
154
163
  const cfgMsg = incompleteCfgMsg();
155
164
  if (cfgMsg) return cfgMsg;
156
165
  let runInteractions = "";
166
+ let triggering_row_id;
167
+ if (table_id) {
168
+ const table = Table.findOne(table_id);
169
+ const pk = table?.pk_name;
170
+ if (table && state[pk])
171
+ //triggering_row = await table.getRow({ [pk]: state[pk] });
172
+ triggering_row_id = state[pk];
173
+ }
157
174
  if (state.run_id) {
158
175
  const run = prevRuns.find((r) => r.id == state.run_id);
159
176
  const interactMarkups = [];
@@ -303,6 +320,12 @@ const run = async (
303
320
  name: "run_id",
304
321
  value: state.run_id ? +state.run_id : undefined,
305
322
  }),
323
+ input({
324
+ type: "hidden",
325
+ class: "form-control ",
326
+ name: "triggering_row_id",
327
+ value: triggering_row_id || "",
328
+ }),
306
329
  div(
307
330
  { class: "copilot-entry" },
308
331
  textarea({
@@ -441,10 +464,9 @@ const run = async (
441
464
  const $runidin= $("input[name=run_id")
442
465
  const runid = $runidin.val()
443
466
  if(runid)
444
- view_post('${viewname}', 'debug_info', {run_id:runid}, show_agent_debug_info)
467
+ view_post('${viewname}', 'debug_info', {run_id:runid, triggering_row_id:$("input[name=triggering_row_id").val()}, show_agent_debug_info)
445
468
  }
446
469
  function show_agent_debug_info(info) {
447
- console.log(info)
448
470
  ensure_modal_exists_and_closed();
449
471
  $("#scmodal .modal-body").html(info.debug_html);
450
472
  $("#scmodal .modal-title").html(decodeURIComponent("Agent session information"));
@@ -507,8 +529,14 @@ const run = async (
507
529
  };
508
530
 
509
531
  const interact = async (table_id, viewname, config, body, { req, res }) => {
510
- const { userinput, run_id } = body;
532
+ const { userinput, run_id, triggering_row_id } = body;
511
533
  let run;
534
+ let triggering_row;
535
+ if (table_id && triggering_row_id) {
536
+ const table = Table.findOne(table_id);
537
+ const pk = table?.pk_name;
538
+ if (table) triggering_row = await table.getRow({ [pk]: triggering_row_id });
539
+ }
512
540
  if (!run_id || run_id === "undefined")
513
541
  run = await WorkflowRun.create({
514
542
  status: "Running",
@@ -518,6 +546,7 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
518
546
  implemented_fcall_ids: [],
519
547
  interactions: [{ role: "user", content: userinput }],
520
548
  funcalls: {},
549
+ triggering_row_id,
521
550
  },
522
551
  });
523
552
  else {
@@ -563,7 +592,14 @@ const interact = async (table_id, viewname, config, body, { req, res }) => {
563
592
  }
564
593
  const action = await Trigger.findOne({ id: config.action_id });
565
594
 
566
- return await process_interaction(run, action.configuration, req, action.name);
595
+ return await process_interaction(
596
+ run,
597
+ action.configuration,
598
+ req,
599
+ action.name,
600
+ [],
601
+ triggering_row
602
+ );
567
603
  };
568
604
 
569
605
  const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
@@ -578,13 +614,19 @@ const delprevrun = async (table_id, viewname, config, body, { req, res }) => {
578
614
  };
579
615
 
580
616
  const debug_info = async (table_id, viewname, config, body, { req, res }) => {
581
- const { run_id } = body;
617
+ const { run_id, triggering_row_id } = body;
582
618
  const action = await Trigger.findOne({ id: config.action_id });
583
-
619
+ let triggering_row;
620
+ if (table_id && triggering_row_id) {
621
+ const table = Table.findOne(table_id);
622
+ const pk = table?.pk_name;
623
+ if (table) triggering_row = await table.getRow({ [pk]: triggering_row_id });
624
+ }
584
625
  const run = await WorkflowRun.findOne({ id: +run_id });
585
626
  const complArgs = await getCompletionArguments(
586
627
  action.configuration,
587
- req.user
628
+ req.user,
629
+ triggering_row
588
630
  );
589
631
  const debug_html = div(
590
632
  div(h4("System prompt"), pre(complArgs.systemPrompt)),
package/common.js CHANGED
@@ -1,11 +1,28 @@
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 { interpolate } = require("@saltcorn/data/utils");
4
5
 
5
6
  const MarkdownIt = require("markdown-it"),
6
7
  md = new MarkdownIt();
7
8
 
9
+ const nubBy = (f, xs) => {
10
+ const vs = new Set();
11
+ return xs.filter((x) => {
12
+ const y = f(x);
13
+ if (vs.has(y)) return false;
14
+ vs.add(y);
15
+ return true;
16
+ });
17
+ };
18
+
8
19
  const get_skills = () => {
20
+ const state = getState();
21
+ const exchange_skills = nubBy(
22
+ (c) => c.constructor.name,
23
+ state.exchange?.agent_skills || []
24
+ );
25
+
9
26
  return [
10
27
  require("./skills/FTSRetrieval"),
11
28
  require("./skills/EmbeddingRetrieval"),
@@ -15,6 +32,7 @@ const get_skills = () => {
15
32
  require("./skills/GenerateImage"),
16
33
  require("./skills/ModelContextProtocol"),
17
34
  //require("./skills/AdaptiveFeedback"),
35
+ ...exchange_skills,
18
36
  ];
19
37
  };
20
38
 
@@ -61,14 +79,16 @@ const find_image_tool = (config) => {
61
79
  }
62
80
  };
63
81
 
64
- const getCompletionArguments = async (config, user) => {
82
+ const getCompletionArguments = async (config, user, triggering_row) => {
65
83
  let tools = [];
66
84
 
67
- let sysPrompts = [config.sys_prompt];
85
+ let sysPrompts = [
86
+ interpolate(config.sys_prompt, triggering_row || {}, user, "System prompt"),
87
+ ];
68
88
 
69
89
  const skills = get_skill_instances(config);
70
90
  for (const skill of skills) {
71
- const sysPr = await skill.systemPrompt?.({ user });
91
+ const sysPr = await skill.systemPrompt?.({ user, triggering_row });
72
92
  if (sysPr) sysPrompts.push(sysPr);
73
93
  const skillTools = skill.provideTools?.();
74
94
  if (skillTools && Array.isArray(skillTools)) tools.push(...skillTools);
@@ -163,9 +183,14 @@ const process_interaction = async (
163
183
  config,
164
184
  req,
165
185
  agent_label = "Copilot",
166
- prevResponses = []
186
+ prevResponses = [],
187
+ triggering_row = {}
167
188
  ) => {
168
- const complArgs = await getCompletionArguments(config, req.user);
189
+ const complArgs = await getCompletionArguments(
190
+ config,
191
+ req.user,
192
+ triggering_row
193
+ );
169
194
  complArgs.chat = run.context.interactions.map(only_response_text_if_present);
170
195
  //complArgs.debugResult = true;
171
196
  //console.log("complArgs", JSON.stringify(complArgs, null, 2));
@@ -300,10 +325,14 @@ const process_interaction = async (
300
325
  }
301
326
  }
302
327
  if (hasResult)
303
- return await process_interaction(run, config, req, agent_label, [
304
- ...prevResponses,
305
- ...responses,
306
- ]);
328
+ return await process_interaction(
329
+ run,
330
+ config,
331
+ req,
332
+ agent_label,
333
+ [...prevResponses, ...responses],
334
+ triggering_row
335
+ );
307
336
  } else if (typeof answer === "string")
308
337
  responses.push(wrapSegment(md.render(answer), agent_label));
309
338
 
package/index.js CHANGED
@@ -51,7 +51,8 @@ module.exports = {
51
51
  {
52
52
  name: "sys_prompt",
53
53
  label: "System prompt",
54
- sublabel: "Additional information for the system prompt",
54
+ sublabel:
55
+ "Additional information for the system prompt. Use interpolations <code>{{ }}</code> to access triggering row variables or user",
55
56
  type: "String",
56
57
  fieldview: "textarea",
57
58
  },
@@ -84,7 +85,14 @@ module.exports = {
84
85
  funcalls: {},
85
86
  },
86
87
  });
87
- return await process_interaction(run, configuration, req);
88
+ return await process_interaction(
89
+ run,
90
+ configuration,
91
+ req,
92
+ undefined,
93
+ [],
94
+ row
95
+ );
88
96
  },
89
97
  },
90
98
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/agents",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "description": "AI agents for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {
@@ -74,6 +74,7 @@ class PreloadData {
74
74
  name: "contents_expr",
75
75
  label: "Contents string",
76
76
  type: "String",
77
+ fieldview: "textarea",
77
78
  sublabel:
78
79
  "Use handlebars (<code>{{ }}</code>) to access fields in each retrieved row",
79
80
  },