@scout9/app 1.0.0-alpha.0.9.7 → 1.0.0-alpha.0.9.9

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.
@@ -35338,7 +35338,7 @@ function _loadUserPackageJson() {
35338
35338
  targetPkgUrl = isTest ? packageTestJsonUrl : packageJsonUrl;
35339
35339
  _context2.t0 = JSON;
35340
35340
  _context2.next = 10;
35341
- return fs__default["default"].readFile(new URL(targetPkgUrl, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('dev-2a3c50b5.js', document.baseURI).href))), 'utf-8');
35341
+ return fs__default["default"].readFile(new URL(targetPkgUrl, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('dev-470b6b68.js', document.baseURI).href))), 'utf-8');
35342
35342
  case 10:
35343
35343
  _context2.t1 = _context2.sent;
35344
35344
  pkg = _context2.t0.parse.call(_context2.t0, _context2.t1);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var _rollupPluginBabelHelpers = require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
4
- var dev = require("./dev-2a3c50b5.cjs");
4
+ var dev = require("./dev-470b6b68.cjs");
5
5
  var macros = require("./macros-93b81169.cjs");
6
6
  var require$$0 = require('fs');
7
7
  var require$$2$1 = require('events');
@@ -29483,7 +29483,7 @@ class Body {
29483
29483
  }
29484
29484
  const {
29485
29485
  toFormData
29486
- } = await Promise.resolve().then(function () { return require("./multipart-parser-0a23e9d3.cjs"); });
29486
+ } = await Promise.resolve().then(function () { return require("./multipart-parser-9a0333c4.cjs"); });
29487
29487
  return toFormData(this.body, ct);
29488
29488
  }
29489
29489
 
@@ -41884,7 +41884,7 @@ function _loadUserPackageJson() {
41884
41884
  targetPkgUrl = isTest ? packageTestJsonUrl : packageJsonUrl;
41885
41885
  _context.t0 = JSON;
41886
41886
  _context.next = 10;
41887
- return fs__default["default"].readFile(new URL(targetPkgUrl, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-e9afdc22.js', document.baseURI).href))), 'utf-8');
41887
+ return fs__default["default"].readFile(new URL(targetPkgUrl, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-17797705.js', document.baseURI).href))), 'utf-8');
41888
41888
  case 10:
41889
41889
  _context.t1 = _context.sent;
41890
41890
  pkg = _context.t0.parse.call(_context.t0, _context.t1);
@@ -43176,7 +43176,7 @@ var ProjectFiles = /*#__PURE__*/function () {
43176
43176
  return ProjectFiles;
43177
43177
  }();
43178
43178
 
43179
- var __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-e9afdc22.js', document.baseURI).href)));
43179
+ var __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-17797705.js', document.baseURI).href)));
43180
43180
  var __dirname$1 = path__default["default"].dirname(__filename$1);
43181
43181
  function zipDirectory(source, out) {
43182
43182
  var archive = archiver$1('tar', {
@@ -43391,7 +43391,7 @@ function _buildApp() {
43391
43391
  case 11:
43392
43392
  _context4.t0 = JSON;
43393
43393
  _context4.next = 14;
43394
- return fs__default["default"].readFile(new URL(templatePackagePath, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-e9afdc22.js', document.baseURI).href))), 'utf-8');
43394
+ return fs__default["default"].readFile(new URL(templatePackagePath, (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index-17797705.js', document.baseURI).href))), 'utf-8');
43395
43395
  case 14:
43396
43396
  _context4.t1 = _context4.sent;
43397
43397
  packageTemplate = _context4.t0.parse.call(_context4.t0, _context4.t1);
package/dist/index.cjs CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require("./index-e9afdc22.cjs");
6
- var dev = require("./dev-2a3c50b5.cjs");
5
+ var index = require("./index-17797705.cjs");
6
+ var dev = require("./dev-470b6b68.cjs");
7
7
  require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
8
8
  require("./macros-93b81169.cjs");
9
9
  require('fs');
@@ -2,9 +2,9 @@
2
2
 
3
3
  require('node:fs');
4
4
  require('node:path');
5
- var index = require("./index-e9afdc22.cjs");
5
+ var index = require("./index-17797705.cjs");
6
6
  require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
7
- require("./dev-2a3c50b5.cjs");
7
+ require("./dev-470b6b68.cjs");
8
8
  require('util');
9
9
  require('stream');
10
10
  require('path');
package/dist/spirits.cjs CHANGED
@@ -226,7 +226,7 @@ var Spirits = {
226
226
  newContextMessages,
227
227
  _iterator,
228
228
  _step,
229
- _loop,
229
+ _loop2,
230
230
  slots,
231
231
  hasNoInstructions,
232
232
  hasNoCustomMessage,
@@ -243,10 +243,7 @@ var Spirits = {
243
243
  forwardNote,
244
244
  instructions,
245
245
  removeInstructions,
246
- manualMessage,
247
- scheduled,
248
246
  resetIntent,
249
- secondsDelay,
250
247
  contextUpsert,
251
248
  anticipate,
252
249
  slotFollowup,
@@ -260,14 +257,12 @@ var Spirits = {
260
257
  _slot,
261
258
  slotId,
262
259
  _tasks2,
263
- _iterator4,
264
- _step4,
265
- instruction,
266
260
  _iterator5,
267
261
  _step5,
268
- _loop2,
269
- manualMessageObj,
270
- now,
262
+ instruction,
263
+ _iterator6,
264
+ _step6,
265
+ _loop3,
271
266
  generatorInput,
272
267
  generatorPayload,
273
268
  _generatorPayload$err,
@@ -280,14 +275,17 @@ var Spirits = {
280
275
  _iterator3,
281
276
  _step3,
282
277
  newMessage,
278
+ _transformResponse$me,
283
279
  transformResponse,
284
- _agentMessages,
285
- _lastAgentMessage,
286
- _args4 = arguments;
287
- return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _callee2$(_context4) {
288
- while (1) switch (_context4.prev = _context4.next) {
280
+ transformedMessages,
281
+ _iterator4,
282
+ _step4,
283
+ _loop,
284
+ _args5 = arguments;
285
+ return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _callee2$(_context5) {
286
+ while (1) switch (_context5.prev = _context5.next) {
289
287
  case 0:
290
- onError = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : function () {};
288
+ onError = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : function () {};
291
289
  customer = input.customer, config = input.config, parser = input.parser, contextualizer = input.contextualizer, workflow = input.workflow, generator = input.generator, transformer = input.transformer, idGenerator = input.idGenerator, _input$progress = input.progress, progress = _input$progress === void 0 ? function (message, level, type, payload) {} : _input$progress, messageBefore = input.message, contextBefore = input.context, messagesBefore = input.messages, conversationBefore = input.conversation;
292
290
  conversation = input.conversation, messages = input.messages, context = input.context, message = input.message; // Storing post process events here
293
291
  followup = [];
@@ -416,7 +414,7 @@ var Spirits = {
416
414
  };
417
415
  }(); // 1. Check inputs
418
416
  if (conversation.$agent) {
419
- _context4.next = 17;
417
+ _context5.next = 17;
420
418
  break;
421
419
  }
422
420
  throw new Error("SpiritsError: No agent found in conversation, must define \".$agent\" in the conversation");
@@ -425,13 +423,13 @@ var Spirits = {
425
423
  return p.id === conversation.$agent;
426
424
  });
427
425
  if (persona) {
428
- _context4.next = 22;
426
+ _context5.next = 22;
429
427
  break;
430
428
  }
431
429
  if (!(config.persona || config.personas || config.agents).some(function (a) {
432
430
  return !a.id;
433
431
  })) {
434
- _context4.next = 21;
432
+ _context5.next = 21;
435
433
  break;
436
434
  }
437
435
  throw new Error("SpiritsError: No persona found (\"".concat(conversation.$agent, "\") in provided config, some persona's did not contain an \"id\" (Internal Mapping Error)"));
@@ -441,7 +439,7 @@ var Spirits = {
441
439
  if (messages.every(function (m) {
442
440
  return !!m.id;
443
441
  })) {
444
- _context4.next = 24;
442
+ _context5.next = 24;
445
443
  break;
446
444
  }
447
445
  throw new Error("SpiritsError: Every message must have an \".id\", ensure all messages have an id assigned before running");
@@ -449,7 +447,7 @@ var Spirits = {
449
447
  if (messages.every(function (m) {
450
448
  return m.role === 'customer' || m.role === 'agent' || m.role === 'system' || m.role === 'tool';
451
449
  })) {
452
- _context4.next = 27;
450
+ _context5.next = 27;
453
451
  break;
454
452
  }
455
453
  invalidRoles = messages.filter(function (m) {
@@ -468,10 +466,10 @@ var Spirits = {
468
466
 
469
467
  // 2. Parse the message
470
468
  progress('Parsing message', 'info', 'SET_PROCESSING', 'user');
471
- _context4.next = 31;
469
+ _context5.next = 31;
472
470
  return wrapStep(parser(message.content, 'en'), 'parse');
473
471
  case 31:
474
- parsePayload = _context4.sent;
472
+ parsePayload = _context5.sent;
475
473
  if (parsePayload.intent) {
476
474
  message.intent = parsePayload.intent;
477
475
  }
@@ -560,19 +558,19 @@ var Spirits = {
560
558
 
561
559
  // 3. Run the contextualizer
562
560
  progress('Running contextualizer', 'info', 'SET_PROCESSING', 'system');
563
- _context4.next = 49;
561
+ _context5.next = 49;
564
562
  return wrapStep(contextualizer({
565
563
  conversation: conversation,
566
564
  messages: messages
567
565
  }), 'contextualize');
568
566
  case 49:
569
- newContextMessages = _context4.sent;
567
+ newContextMessages = _context5.sent;
570
568
  _iterator = _rollupPluginBabelHelpers._createForOfIteratorHelper(newContextMessages);
571
- _context4.prev = 51;
572
- _loop = /*#__PURE__*/_rollupPluginBabelHelpers._regeneratorRuntime().mark(function _loop() {
569
+ _context5.prev = 51;
570
+ _loop2 = /*#__PURE__*/_rollupPluginBabelHelpers._regeneratorRuntime().mark(function _loop2() {
573
571
  var contextMessage;
574
- return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _loop$(_context2) {
575
- while (1) switch (_context2.prev = _context2.next) {
572
+ return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _loop2$(_context3) {
573
+ while (1) switch (_context3.prev = _context3.next) {
576
574
  case 0:
577
575
  contextMessage = _step.value;
578
576
  if (!messages.find(function (mes) {
@@ -585,35 +583,35 @@ var Spirits = {
585
583
  }
586
584
  case 2:
587
585
  case "end":
588
- return _context2.stop();
586
+ return _context3.stop();
589
587
  }
590
- }, _loop);
588
+ }, _loop2);
591
589
  });
592
590
  _iterator.s();
593
591
  case 54:
594
592
  if ((_step = _iterator.n()).done) {
595
- _context4.next = 58;
593
+ _context5.next = 58;
596
594
  break;
597
595
  }
598
- return _context4.delegateYield(_loop(), "t0", 56);
596
+ return _context5.delegateYield(_loop2(), "t0", 56);
599
597
  case 56:
600
- _context4.next = 54;
598
+ _context5.next = 54;
601
599
  break;
602
600
  case 58:
603
- _context4.next = 63;
601
+ _context5.next = 63;
604
602
  break;
605
603
  case 60:
606
- _context4.prev = 60;
607
- _context4.t1 = _context4["catch"](51);
608
- _iterator.e(_context4.t1);
604
+ _context5.prev = 60;
605
+ _context5.t1 = _context5["catch"](51);
606
+ _iterator.e(_context5.t1);
609
607
  case 63:
610
- _context4.prev = 63;
608
+ _context5.prev = 63;
611
609
  _iterator.f();
612
- return _context4.finish(63);
610
+ return _context5.finish(63);
613
611
  case 66:
614
612
  // 4. Run the workflow
615
613
  progress('Running workflow', 'info', 'SET_PROCESSING', 'system');
616
- _context4.next = 69;
614
+ _context5.next = 69;
617
615
  return wrapStep(workflow({
618
616
  messages: messages,
619
617
  conversation: conversation,
@@ -643,16 +641,53 @@ var Spirits = {
643
641
  }, []);
644
642
  });
645
643
  case 69:
646
- slots = _context4.sent;
644
+ slots = _context5.sent;
647
645
  hasNoInstructions = slots.every(function (s) {
648
646
  return !s.instructions || Array.isArray(s.instructions) && s.instructions.length === 0;
649
647
  });
650
648
  hasNoCustomMessage = slots.every(function (s) {
651
649
  return !s.message;
652
650
  });
653
- messagesToTransform = slots.filter(function (s) {
654
- return !!s.message && _rollupPluginBabelHelpers._typeof(s.message) === 'object' && !!s.message.transform;
655
- });
651
+ messagesToTransform = slots.reduce(function (acc, slot, index) {
652
+ var m = slot === null || slot === void 0 ? void 0 : slot.message;
653
+
654
+ // ignore empty
655
+ if (!m) return acc;
656
+ var adjusted = {
657
+ id: idGenerator('agent'),
658
+ role: 'agent',
659
+ // ...m,
660
+ time: new Date().toISOString(),
661
+ content: typeof m === 'string' ? m : m.content === 'string' ? m.content : ''
662
+ };
663
+ if (!(typeof m === 'string')) {
664
+ Object.assign(adjusted, m);
665
+ }
666
+
667
+ // only include those explicitly requesting transform
668
+ if (!m.transform) {
669
+ adjusted.ignoreTransform = true;
670
+ }
671
+ if (slot.scheduled) {
672
+ adjusted.time = new Date(slot.scheduled * 1000).toISOString();
673
+ adjusted.scheduled = adjusted.time;
674
+ } else if (slot.secondsDelay) {
675
+ var now = new Date();
676
+ now.setSeconds(now.getSeconds() + slot.secondsDelay);
677
+ adjusted.time = now.toISOString();
678
+ adjusted.delayInSeconds = slot.secondsDelay;
679
+ }
680
+ if (!adjusted.content && !adjusted.tool_calls) {
681
+ progress("Slot ".concat(index, " input error"), 'failed', 'SLOT_INPUT_ERROR', {
682
+ error: "Expected slots[".concat(index, "].message.content to exist (unless tool_calls provided)")
683
+ });
684
+ return acc;
685
+ } else if (!adjusted.tool_calls && adjusted.role === 'agent') {
686
+ adjusted.contentGenerated = m.content;
687
+ }
688
+ acc.push(adjusted);
689
+ return acc;
690
+ }, []);
656
691
  previousLockAttempt = conversation.lockAttempts || 0; // Used to track
657
692
  if (hasNoInstructions && noNewContext) {
658
693
  conversation = incrementLockAttempt(conversation, config);
@@ -669,20 +704,20 @@ var Spirits = {
669
704
  resettedIntent = false;
670
705
  /** @type {Array<string> | undefined} */
671
706
  _iterator2 = _rollupPluginBabelHelpers._createForOfIteratorHelper(slots);
672
- _context4.prev = 77;
707
+ _context5.prev = 77;
673
708
  _iterator2.s();
674
709
  case 79:
675
710
  if ((_step2 = _iterator2.n()).done) {
676
- _context4.next = 150;
711
+ _context5.next = 134;
677
712
  break;
678
713
  }
679
- _step2$value = _step2.value, forward = _step2$value.forward, forwardNote = _step2$value.forwardNote, instructions = _step2$value.instructions, removeInstructions = _step2$value.removeInstructions, manualMessage = _step2$value.message, scheduled = _step2$value.scheduled, resetIntent = _step2$value.resetIntent, secondsDelay = _step2$value.secondsDelay, contextUpsert = _step2$value.contextUpsert, anticipate = _step2$value.anticipate, slotFollowup = _step2$value.followup, slotEntityContextUpsert = _step2$value.entityContextUpsert, tasks = _step2$value.tasks;
714
+ _step2$value = _step2.value, forward = _step2$value.forward, forwardNote = _step2$value.forwardNote, instructions = _step2$value.instructions, removeInstructions = _step2$value.removeInstructions, _step2$value.message, _step2$value.scheduled, resetIntent = _step2$value.resetIntent, _step2$value.secondsDelay, contextUpsert = _step2$value.contextUpsert, anticipate = _step2$value.anticipate, slotFollowup = _step2$value.followup, slotEntityContextUpsert = _step2$value.entityContextUpsert, tasks = _step2$value.tasks;
680
715
  if (!anticipate) {
681
- _context4.next = 94;
716
+ _context5.next = 94;
682
717
  break;
683
718
  }
684
719
  if (!Array.isArray(anticipate)) {
685
- _context4.next = 89;
720
+ _context5.next = 89;
686
721
  break;
687
722
  }
688
723
  // 'literal' anticipation
@@ -702,11 +737,11 @@ var Spirits = {
702
737
  slots: _slots,
703
738
  map: map
704
739
  });
705
- _context4.next = 94;
740
+ _context5.next = 94;
706
741
  break;
707
742
  case 89:
708
743
  if (!('yes' in anticipate && 'no' in anticipate && 'did' in anticipate)) {
709
- _context4.next = 93;
744
+ _context5.next = 93;
710
745
  break;
711
746
  }
712
747
  // "did" anticipation
@@ -718,7 +753,7 @@ var Spirits = {
718
753
  },
719
754
  did: anticipate.did
720
755
  });
721
- _context4.next = 94;
756
+ _context5.next = 94;
722
757
  break;
723
758
  case 93:
724
759
  throw new Error("Invalid anticipate payload \"".concat(JSON.stringify(anticipate), "\""));
@@ -778,25 +813,25 @@ var Spirits = {
778
813
 
779
814
  // Insert instructions context
780
815
  if (!instructions) {
781
- _context4.next = 113;
816
+ _context5.next = 113;
782
817
  break;
783
818
  }
784
819
  if (!(typeof instructions === 'string')) {
785
- _context4.next = 103;
820
+ _context5.next = 103;
786
821
  break;
787
822
  }
788
823
  addInstruction(instructions, previousLockAttempt);
789
- _context4.next = 113;
824
+ _context5.next = 113;
790
825
  break;
791
826
  case 103:
792
827
  if (!Array.isArray(instructions)) {
793
- _context4.next = 108;
828
+ _context5.next = 108;
794
829
  break;
795
830
  }
796
- _iterator4 = _rollupPluginBabelHelpers._createForOfIteratorHelper(instructions);
831
+ _iterator5 = _rollupPluginBabelHelpers._createForOfIteratorHelper(instructions);
797
832
  try {
798
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
799
- instruction = _step4.value;
833
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
834
+ instruction = _step5.value;
800
835
  if (typeof instruction === 'string') {
801
836
  addInstruction(instruction, previousLockAttempt);
802
837
  } else {
@@ -804,35 +839,35 @@ var Spirits = {
804
839
  }
805
840
  }
806
841
  } catch (err) {
807
- _iterator4.e(err);
842
+ _iterator5.e(err);
808
843
  } finally {
809
- _iterator4.f();
844
+ _iterator5.f();
810
845
  }
811
- _context4.next = 113;
846
+ _context5.next = 113;
812
847
  break;
813
848
  case 108:
814
849
  if (!(_rollupPluginBabelHelpers._typeof(instructions) === 'object' && 'content' in instructions)) {
815
- _context4.next = 112;
850
+ _context5.next = 112;
816
851
  break;
817
852
  }
818
853
  addInstruction(instructions.content, previousLockAttempt, instructions.id);
819
- _context4.next = 113;
854
+ _context5.next = 113;
820
855
  break;
821
856
  case 112:
822
857
  throw new Error("SpiritsError: instructions must be a string or array or {content: \"<instruction>\"}, got: ".concat(JSON.stringify(instructions)));
823
858
  case 113:
824
859
  if (!removeInstructions) {
825
- _context4.next = 130;
860
+ _context5.next = 130;
826
861
  break;
827
862
  }
828
- _iterator5 = _rollupPluginBabelHelpers._createForOfIteratorHelper(removeInstructions);
829
- _context4.prev = 115;
830
- _loop2 = /*#__PURE__*/_rollupPluginBabelHelpers._regeneratorRuntime().mark(function _loop2() {
863
+ _iterator6 = _rollupPluginBabelHelpers._createForOfIteratorHelper(removeInstructions);
864
+ _context5.prev = 115;
865
+ _loop3 = /*#__PURE__*/_rollupPluginBabelHelpers._regeneratorRuntime().mark(function _loop3() {
831
866
  var instructionId, index;
832
- return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _loop2$(_context3) {
833
- while (1) switch (_context3.prev = _context3.next) {
867
+ return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _loop3$(_context4) {
868
+ while (1) switch (_context4.prev = _context4.next) {
834
869
  case 0:
835
- instructionId = _step5.value;
870
+ instructionId = _step6.value;
836
871
  index = messages.findIndex(function (m) {
837
872
  return m.id === instructionId;
838
873
  });
@@ -846,76 +881,67 @@ var Spirits = {
846
881
  }
847
882
  case 3:
848
883
  case "end":
849
- return _context3.stop();
884
+ return _context4.stop();
850
885
  }
851
- }, _loop2);
886
+ }, _loop3);
852
887
  });
853
- _iterator5.s();
888
+ _iterator6.s();
854
889
  case 118:
855
- if ((_step5 = _iterator5.n()).done) {
856
- _context4.next = 122;
890
+ if ((_step6 = _iterator6.n()).done) {
891
+ _context5.next = 122;
857
892
  break;
858
893
  }
859
- return _context4.delegateYield(_loop2(), "t2", 120);
894
+ return _context5.delegateYield(_loop3(), "t2", 120);
860
895
  case 120:
861
- _context4.next = 118;
896
+ _context5.next = 118;
862
897
  break;
863
898
  case 122:
864
- _context4.next = 127;
899
+ _context5.next = 127;
865
900
  break;
866
901
  case 124:
867
- _context4.prev = 124;
868
- _context4.t3 = _context4["catch"](115);
869
- _iterator5.e(_context4.t3);
902
+ _context5.prev = 124;
903
+ _context5.t3 = _context5["catch"](115);
904
+ _iterator6.e(_context5.t3);
870
905
  case 127:
871
- _context4.prev = 127;
872
- _iterator5.f();
873
- return _context4.finish(127);
906
+ _context5.prev = 127;
907
+ _iterator6.f();
908
+ return _context5.finish(127);
874
909
  case 130:
875
- if (!manualMessage) {
876
- _context4.next = 146;
877
- break;
878
- }
879
- /** @type {import('@scout9/admin').Message} */
880
- manualMessageObj = {
881
- id: idGenerator('persona'),
882
- role: 'agent',
883
- // @TODO switch role to persona
884
- content: '',
885
- time: new Date().toISOString()
886
- };
887
- if (!(_rollupPluginBabelHelpers._typeof(manualMessage) === 'object')) {
888
- _context4.next = 138;
889
- break;
890
- }
891
- Object.assign(manualMessageObj, manualMessage);
892
- manualMessageObj.role = 'agent';
893
- manualMessageObj.time = new Date().toISOString();
894
- _context4.next = 143;
895
- break;
896
- case 138:
897
- if (!(typeof manualMessage === 'string')) {
898
- _context4.next = 142;
899
- break;
900
- }
901
- manualMessageObj.content = manualMessage;
902
- _context4.next = 143;
903
- break;
904
- case 142:
905
- throw new Error('Manual message must be of type "string" or "DirectMessage"');
906
- case 143:
907
- if (scheduled) {
908
- manualMessageObj.time = new Date(scheduled * 1000).toISOString();
909
- manualMessageObj.scheduled = manualMessageObj.time;
910
- } else if (secondsDelay) {
911
- now = new Date();
912
- now.setSeconds(now.getSeconds() + secondsDelay);
913
- manualMessageObj.time = now.toISOString();
914
- manualMessageObj.delayInSeconds = secondsDelay;
915
- }
916
- messages.push(manualMessageObj);
917
- progress('Added manual message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
918
- case 146:
910
+ // @TODO this logic is now handled at messagesToTransform's initialization, maybe move back down here
911
+ // if (manualMessage) {
912
+
913
+ // /** @type {import('@scout9/admin').Message} */
914
+ // let manualMessageObj = {
915
+ // id: idGenerator('persona'),
916
+ // role: 'agent', // @TODO switch role to persona
917
+ // content: '',
918
+ // time: new Date().toISOString()
919
+ // };
920
+ // if (typeof manualMessage === 'object') {
921
+ // Object.assign(manualMessageObj, manualMessage);
922
+ // manualMessageObj.role = 'agent';
923
+ // manualMessageObj.time = new Date().toISOString();
924
+ // } else if (typeof manualMessage === 'string') {
925
+ // manualMessageObj.content = manualMessage;
926
+ // } else {
927
+ // throw new Error('Manual message must be of type "string" or "DirectMessage"');
928
+ // }
929
+
930
+ // if (scheduled) {
931
+ // manualMessageObj.time = new Date(scheduled * 1000).toISOString();
932
+ // manualMessageObj.scheduled = manualMessageObj.time;
933
+ // } else if (secondsDelay) {
934
+ // const now = new Date();
935
+ // now.setSeconds(now.getSeconds() + secondsDelay);
936
+ // manualMessageObj.time = now.toISOString();
937
+ // manualMessageObj.delayInSeconds = secondsDelay;
938
+ // }
939
+ // // @TODO should we mark this as ignored transform?
940
+ // manualMessageObj.ignoreTransform = true;
941
+ // messagesToTransform.push(manualMessageObj);
942
+ // progress('Added manual message', 'info', 'ADD_MESSAGE', messagesToTransform[messagesToTransform.length - 1]);
943
+ // }
944
+
919
945
  if (contextUpsert) {
920
946
  context = updateContext(context, contextUpsert);
921
947
  progress('Upserted context', 'info', 'UPDATE_CONTEXT', contextUpsert);
@@ -923,21 +949,21 @@ var Spirits = {
923
949
  if (resetIntent) {
924
950
  resettedIntent = true;
925
951
  }
926
- case 148:
927
- _context4.next = 79;
952
+ case 132:
953
+ _context5.next = 79;
928
954
  break;
929
- case 150:
930
- _context4.next = 155;
955
+ case 134:
956
+ _context5.next = 139;
931
957
  break;
932
- case 152:
933
- _context4.prev = 152;
934
- _context4.t4 = _context4["catch"](77);
935
- _iterator2.e(_context4.t4);
936
- case 155:
937
- _context4.prev = 155;
958
+ case 136:
959
+ _context5.prev = 136;
960
+ _context5.t4 = _context5["catch"](77);
961
+ _iterator2.e(_context5.t4);
962
+ case 139:
963
+ _context5.prev = 139;
938
964
  _iterator2.f();
939
- return _context4.finish(155);
940
- case 158:
965
+ return _context5.finish(139);
966
+ case 142:
941
967
  if (resettedIntent && !_forward) {
942
968
  conversation.intent = null;
943
969
  conversation.intentScore = null;
@@ -956,14 +982,14 @@ var Spirits = {
956
982
  // 5. Generate response
957
983
  // If conversation previously locked, don't generate
958
984
  if (input.conversation.locked) {
959
- _context4.next = 200;
985
+ _context5.next = 198;
960
986
  break;
961
987
  }
962
988
  if (!((!conversation.locked || !hasNoInstructions) && !!hasNoCustomMessage)) {
963
- _context4.next = 178;
989
+ _context5.next = 162;
964
990
  break;
965
991
  }
966
- _context4.prev = 161;
992
+ _context5.prev = 145;
967
993
  progress('Generating message', 'info', 'SET_PROCESSING', 'system');
968
994
 
969
995
  /** @type {import('@scout9/admin').GenerateRequestOneOf1} */
@@ -977,10 +1003,10 @@ var Spirits = {
977
1003
  if (!!_tasks && Array.isArray(_tasks) && !!_tasks.length) {
978
1004
  generatorInput.tasks = _tasks;
979
1005
  }
980
- _context4.next = 167;
1006
+ _context5.next = 151;
981
1007
  return wrapStep(generator(generatorInput), 'generate');
982
- case 167:
983
- generatorPayload = _context4.sent;
1008
+ case 151:
1009
+ generatorPayload = _context5.sent;
984
1010
  if (!generatorPayload.send) {
985
1011
  progress('Generated response', 'failed', undefined, {
986
1012
  error: ((_generatorPayload$err = generatorPayload.errors) === null || _generatorPayload$err === void 0 ? void 0 : _generatorPayload$err.join('\n\n')) || 'Unknown Reason'
@@ -1014,6 +1040,7 @@ var Spirits = {
1014
1040
  var base = {
1015
1041
  role: message.role,
1016
1042
  content: message.content,
1043
+ contentGenerated: message.content,
1017
1044
  id: idGenerator(message.role),
1018
1045
  time: isoTime
1019
1046
  };
@@ -1053,8 +1080,11 @@ var Spirits = {
1053
1080
  try {
1054
1081
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1055
1082
  newMessage = _step3.value;
1056
- messages.push(newMessage);
1057
- progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
1083
+ // messages.push(newMessage); switched to push to messages after transform is complete
1084
+ messagesToTransform.push(_rollupPluginBabelHelpers._objectSpread2({
1085
+ contentGenerated: newMessage.content
1086
+ }, newMessage));
1087
+ progress('Added agent message for transform', 'info', 'ADD_MESSAGE', messagesToTransform[messagesToTransform.length - 1]);
1058
1088
  }
1059
1089
  } catch (err) {
1060
1090
  _iterator3.e(err);
@@ -1072,80 +1102,128 @@ var Spirits = {
1072
1102
  }
1073
1103
  }
1074
1104
  }
1075
- _context4.next = 176;
1105
+ _context5.next = 160;
1076
1106
  break;
1077
- case 171:
1078
- _context4.prev = 171;
1079
- _context4.t5 = _context4["catch"](161);
1080
- onError(_context4.t5);
1081
- console.error("Spirits: Locking conversation, error generating response: ".concat(_context4.t5.message));
1082
- conversation = lockConversation(conversation, 'API: ' + _context4.t5.message);
1083
- case 176:
1084
- _context4.next = 179;
1107
+ case 155:
1108
+ _context5.prev = 155;
1109
+ _context5.t5 = _context5["catch"](145);
1110
+ onError(_context5.t5);
1111
+ console.error("Spirits: Locking conversation, error generating response: ".concat(_context5.t5.message));
1112
+ conversation = lockConversation(conversation, 'API: ' + _context5.t5.message);
1113
+ case 160:
1114
+ _context5.next = 163;
1085
1115
  break;
1086
- case 178:
1116
+ case 162:
1087
1117
  onStatus('generate', 'ignored');
1088
- case 179:
1118
+ case 163:
1089
1119
  if (!(messagesToTransform.length && transformer)) {
1090
- _context4.next = 197;
1120
+ _context5.next = 195;
1091
1121
  break;
1092
1122
  }
1093
- _context4.prev = 180;
1094
- _context4.next = 183;
1123
+ _context5.prev = 164;
1124
+ _context5.next = 167;
1095
1125
  return wrapStep(transformer({
1096
- message: messagesToTransform,
1126
+ // message: messagesToTransform,
1127
+ addedMessages: messagesToTransform,
1097
1128
  persona: persona,
1098
1129
  customer: customer.id,
1099
1130
  messages: messages,
1100
1131
  context: context
1101
1132
  }), 'transform');
1102
- case 183:
1103
- transformResponse = _context4.sent;
1133
+ case 167:
1134
+ transformResponse = _context5.sent;
1104
1135
  progress('Generated response', 'success', undefined, undefined);
1105
- // Check if already had message
1106
- _agentMessages = messages.filter(function (m) {
1107
- return m.role === 'agent';
1136
+
1137
+ // @TODO check for duplicates, or have already sent the message
1138
+ transformedMessages = (_transformResponse$me = transformResponse.messages) !== null && _transformResponse$me !== void 0 && _transformResponse$me.length ? transformResponse.messages : [{
1139
+ role: 'agent',
1140
+ content: transformResponse.message
1141
+ }];
1142
+ _iterator4 = _rollupPluginBabelHelpers._createForOfIteratorHelper(transformedMessages);
1143
+ _context5.prev = 171;
1144
+ _loop = /*#__PURE__*/_rollupPluginBabelHelpers._regeneratorRuntime().mark(function _loop() {
1145
+ var message, adjusted, prior, _adjusted$contentGene, _adjusted$contentTran;
1146
+ return _rollupPluginBabelHelpers._regeneratorRuntime().wrap(function _loop$(_context2) {
1147
+ while (1) switch (_context2.prev = _context2.next) {
1148
+ case 0:
1149
+ message = _step4.value;
1150
+ adjusted = _rollupPluginBabelHelpers._objectSpread2({
1151
+ id: idGenerator('agent'),
1152
+ role: 'agent',
1153
+ time: new Date().toISOString()
1154
+ }, message);
1155
+ if (adjusted.role === 'agent' && adjusted.content && !adjusted.ignoreTransform && !adjusted.tool_calls) {
1156
+ prior = messagesToTransform.find(function (m) {
1157
+ return m.id === message.id;
1158
+ });
1159
+ if (prior) {
1160
+ adjusted.contentGenerated = prior.content; // BEFORE (original)
1161
+ adjusted.contentTransformed = adjusted.content; // AFTER (transformed)
1162
+ } else {
1163
+ // fallback if transformer changed ids
1164
+ adjusted.contentGenerated = (_adjusted$contentGene = adjusted.contentGenerated) !== null && _adjusted$contentGene !== void 0 ? _adjusted$contentGene : adjusted.content;
1165
+ adjusted.contentTransformed = (_adjusted$contentTran = adjusted.contentTransformed) !== null && _adjusted$contentTran !== void 0 ? _adjusted$contentTran : adjusted.content;
1166
+ }
1167
+ }
1168
+ if (adjusted.role === 'agent' && adjusted.content && !adjusted.ignoreTransform && !adjusted.tool_calls && !adjusted.contentTransformed) {
1169
+ progress('missing contentTransformed on a generated message', 'warning', undefined, adjusted);
1170
+ adjusted.contentTransformed = adjusted.content;
1171
+ }
1172
+ messages.push(adjusted);
1173
+ progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
1174
+ case 6:
1175
+ case "end":
1176
+ return _context2.stop();
1177
+ }
1178
+ }, _loop);
1108
1179
  });
1109
- _lastAgentMessage = _agentMessages[_agentMessages.length - 1];
1110
- if (_lastAgentMessage && _lastAgentMessage.content && _lastAgentMessage.content === transformResponse.message) {
1111
- // Error should not have happened
1112
- conversation = lockConversation(conversation, 'Duplicate message');
1113
- } else {
1114
- messages.push({
1115
- id: idGenerator('agent'),
1116
- role: 'agent',
1117
- content: transformResponse.message,
1118
- time: new Date().toISOString()
1119
- });
1120
- progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
1180
+ _iterator4.s();
1181
+ case 174:
1182
+ if ((_step4 = _iterator4.n()).done) {
1183
+ _context5.next = 178;
1184
+ break;
1121
1185
  }
1122
-
1123
- // }
1124
- _context4.next = 195;
1186
+ return _context5.delegateYield(_loop(), "t6", 176);
1187
+ case 176:
1188
+ _context5.next = 174;
1125
1189
  break;
1126
- case 190:
1127
- _context4.prev = 190;
1128
- _context4.t6 = _context4["catch"](180);
1129
- console.error("Locking conversation, error transforming response: ".concat(_context4.t6.message));
1130
- conversation = lockConversation(conversation, 'API: ' + _context4.t6.message);
1131
- onError(_context4.t6);
1132
- case 195:
1133
- _context4.next = 198;
1190
+ case 178:
1191
+ _context5.next = 183;
1192
+ break;
1193
+ case 180:
1194
+ _context5.prev = 180;
1195
+ _context5.t7 = _context5["catch"](171);
1196
+ _iterator4.e(_context5.t7);
1197
+ case 183:
1198
+ _context5.prev = 183;
1199
+ _iterator4.f();
1200
+ return _context5.finish(183);
1201
+ case 186:
1202
+ _context5.next = 193;
1203
+ break;
1204
+ case 188:
1205
+ _context5.prev = 188;
1206
+ _context5.t8 = _context5["catch"](164);
1207
+ console.error("Locking conversation, error transforming response: ".concat(_context5.t8.message));
1208
+ conversation = lockConversation(conversation, 'API: ' + _context5.t8.message);
1209
+ onError(_context5.t8);
1210
+ case 193:
1211
+ _context5.next = 196;
1134
1212
  break;
1135
- case 197:
1213
+ case 195:
1136
1214
  if (messagesToTransform.length) {
1137
1215
  console.warn("No transformer provided");
1138
1216
  onStatus('transform', 'ignored');
1139
1217
  }
1140
- case 198:
1141
- _context4.next = 202;
1218
+ case 196:
1219
+ _context5.next = 200;
1142
1220
  break;
1143
- case 200:
1221
+ case 198:
1144
1222
  onStatus('generate', 'ignored');
1145
1223
  onStatus('transform', 'ignored');
1146
- case 202:
1224
+ case 200:
1147
1225
  progress('Parsing message', 'info', 'SET_PROCESSING', null);
1148
- return _context4.abrupt("return", {
1226
+ return _context5.abrupt("return", {
1149
1227
  conversation: {
1150
1228
  before: conversationBefore,
1151
1229
  after: conversation,
@@ -1167,11 +1245,11 @@ var Spirits = {
1167
1245
  followup: followup,
1168
1246
  entityContextUpsert: entityContextUpsert
1169
1247
  });
1170
- case 204:
1248
+ case 202:
1171
1249
  case "end":
1172
- return _context4.stop();
1250
+ return _context5.stop();
1173
1251
  }
1174
- }, _callee2, null, [[51, 60, 63, 66], [77, 152, 155, 158], [115, 124, 127, 130], [161, 171], [180, 190]]);
1252
+ }, _callee2, null, [[51, 60, 63, 66], [77, 136, 139, 142], [115, 124, 127, 130], [145, 155], [164, 188], [171, 180, 183, 186]]);
1175
1253
  }));
1176
1254
  function customer(_x) {
1177
1255
  return _customer.apply(this, arguments);
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dev = require("./dev-2a3c50b5.cjs");
5
+ var dev = require("./dev-470b6b68.cjs");
6
6
  require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
7
7
  require('util');
8
8
  require('stream');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scout9/app",
3
- "version": "1.0.0-alpha.0.9.7",
3
+ "version": "1.0.0-alpha.0.9.9",
4
4
  "description": "Build and deploy your Scout9 app for SMS auto replies",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -108,9 +108,9 @@
108
108
  * @param {any} message
109
109
  * @returns {string}
110
110
  */
111
- export function messageKey (message) {
111
+ export function messageKey(message) {
112
112
  // @TODO consider `${msg.role}::${msg.content}` for stronger uniqueness
113
- return String(message.content || (message.tool_calls ? JSON.stringify(message.tool_calls) : ''));
113
+ return String(message.content || (message.tool_calls ? JSON.stringify(message.tool_calls) : ''));
114
114
  }
115
115
 
116
116
  class SpiritError extends Error {
@@ -302,7 +302,7 @@ export const Spirits = {
302
302
  };
303
303
 
304
304
  const onStatus = (statusType, completeOrError = true) => {
305
- progress(`${statusType}: ${completeOrError}`, 'info', 'STATUS', {[statusType]: completeOrError});
305
+ progress(`${statusType}: ${completeOrError}`, 'info', 'STATUS', { [statusType]: completeOrError });
306
306
  }
307
307
 
308
308
  /**
@@ -472,7 +472,51 @@ export const Spirits = {
472
472
  }, []));
473
473
  const hasNoInstructions = slots.every(s => !s.instructions || (Array.isArray(s.instructions) && s.instructions.length === 0));
474
474
  const hasNoCustomMessage = slots.every(s => !s.message);
475
- const messagesToTransform = slots.filter(s => !!s.message && typeof s.message === 'object' && !!s.message.transform);
475
+ const messagesToTransform = slots.reduce((acc, slot, index) => {
476
+ const m = slot?.message;
477
+
478
+ // ignore empty
479
+ if (!m) return acc;
480
+
481
+ const adjusted = {
482
+ id: idGenerator('agent'),
483
+ role: 'agent',
484
+ // ...m,
485
+ time: new Date().toISOString(),
486
+ content: typeof m ==='string' ? m : m.content === 'string' ? m.content : '',
487
+ };
488
+
489
+ if (!(typeof m === 'string')) {
490
+ Object.assign(adjusted, m);
491
+ }
492
+
493
+ // only include those explicitly requesting transform
494
+ if (!m.transform) {
495
+ adjusted.ignoreTransform = true;
496
+ }
497
+
498
+
499
+ if (slot.scheduled) {
500
+ adjusted.time = new Date(slot.scheduled * 1000).toISOString();
501
+ adjusted.scheduled = adjusted.time;
502
+ } else if (slot.secondsDelay) {
503
+ const now = new Date();
504
+ now.setSeconds(now.getSeconds() + slot.secondsDelay);
505
+ adjusted.time = now.toISOString();
506
+ adjusted.delayInSeconds = slot.secondsDelay;
507
+ }
508
+ if (!adjusted.content && !adjusted.tool_calls) {
509
+ progress(`Slot ${index} input error`, 'failed', 'SLOT_INPUT_ERROR', {
510
+ error: `Expected slots[${index}].message.content to exist (unless tool_calls provided)`,
511
+ });
512
+ return acc;
513
+ } else if (!adjusted.tool_calls && adjusted.role === 'agent') {
514
+ adjusted.contentGenerated = m.content;
515
+ }
516
+ acc.push(adjusted);
517
+ return acc;
518
+ }, []);
519
+
476
520
  const previousLockAttempt = conversation.lockAttempts || 0; // Used to track
477
521
 
478
522
  if (hasNoInstructions && noNewContext) {
@@ -632,37 +676,40 @@ export const Spirits = {
632
676
  }
633
677
  }
634
678
 
635
- if (manualMessage) {
636
-
637
- /** @type {import('@scout9/admin').Message} */
638
- let manualMessageObj = {
639
- id: idGenerator('persona'),
640
- role: 'agent', // @TODO switch role to persona
641
- content: '',
642
- time: new Date().toISOString()
643
- };
644
- if (typeof manualMessage === 'object') {
645
- Object.assign(manualMessageObj, manualMessage);
646
- manualMessageObj.role = 'agent';
647
- manualMessageObj.time = new Date().toISOString();
648
- } else if (typeof manualMessage === 'string') {
649
- manualMessageObj.content = manualMessage;
650
- } else {
651
- throw new Error('Manual message must be of type "string" or "DirectMessage"');
652
- }
653
-
654
- if (scheduled) {
655
- manualMessageObj.time = new Date(scheduled * 1000).toISOString();
656
- manualMessageObj.scheduled = manualMessageObj.time;
657
- } else if (secondsDelay) {
658
- const now = new Date();
659
- now.setSeconds(now.getSeconds() + secondsDelay);
660
- manualMessageObj.time = now.toISOString();
661
- manualMessageObj.delayInSeconds = secondsDelay;
662
- }
663
- messages.push(manualMessageObj);
664
- progress('Added manual message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
665
- }
679
+ // @TODO this logic is now handled at messagesToTransform's initialization, maybe move back down here
680
+ // if (manualMessage) {
681
+
682
+ // /** @type {import('@scout9/admin').Message} */
683
+ // let manualMessageObj = {
684
+ // id: idGenerator('persona'),
685
+ // role: 'agent', // @TODO switch role to persona
686
+ // content: '',
687
+ // time: new Date().toISOString()
688
+ // };
689
+ // if (typeof manualMessage === 'object') {
690
+ // Object.assign(manualMessageObj, manualMessage);
691
+ // manualMessageObj.role = 'agent';
692
+ // manualMessageObj.time = new Date().toISOString();
693
+ // } else if (typeof manualMessage === 'string') {
694
+ // manualMessageObj.content = manualMessage;
695
+ // } else {
696
+ // throw new Error('Manual message must be of type "string" or "DirectMessage"');
697
+ // }
698
+
699
+ // if (scheduled) {
700
+ // manualMessageObj.time = new Date(scheduled * 1000).toISOString();
701
+ // manualMessageObj.scheduled = manualMessageObj.time;
702
+ // } else if (secondsDelay) {
703
+ // const now = new Date();
704
+ // now.setSeconds(now.getSeconds() + secondsDelay);
705
+ // manualMessageObj.time = now.toISOString();
706
+ // manualMessageObj.delayInSeconds = secondsDelay;
707
+ // }
708
+ // // @TODO should we mark this as ignored transform?
709
+ // manualMessageObj.ignoreTransform = true;
710
+ // messagesToTransform.push(manualMessageObj);
711
+ // progress('Added manual message', 'info', 'ADD_MESSAGE', messagesToTransform[messagesToTransform.length - 1]);
712
+ // }
666
713
 
667
714
  if (contextUpsert) {
668
715
  context = updateContext(context, contextUpsert);
@@ -758,6 +805,7 @@ export const Spirits = {
758
805
  const base = {
759
806
  role: message.role,
760
807
  content: message.content,
808
+ contentGenerated: message.content,
761
809
  id: idGenerator(message.role),
762
810
  time: isoTime,
763
811
  };
@@ -786,13 +834,14 @@ export const Spirits = {
786
834
  ).items;
787
835
 
788
836
 
789
- if (lastAgentMessage && lastAgentMessage.content && addedMessages.some((message) => message.content === lastAgentMessage.content)) {
837
+ if (lastAgentMessage && lastAgentMessage.content && addedMessages.some((message) => message.content === lastAgentMessage.content)) {
790
838
  // Error should not have happened
791
839
  conversation = lockConversation(conversation, 'Duplicate message');
792
840
  } else {
793
841
  for (const newMessage of addedMessages) {
794
- messages.push(newMessage);
795
- progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
842
+ // messages.push(newMessage); switched to push to messages after transform is complete
843
+ messagesToTransform.push({contentGenerated: newMessage.content, ...newMessage});
844
+ progress('Added agent message for transform', 'info', 'ADD_MESSAGE', messagesToTransform[messagesToTransform.length - 1]);
796
845
  }
797
846
  }
798
847
 
@@ -818,35 +867,55 @@ export const Spirits = {
818
867
  onStatus('generate', 'ignored');
819
868
  }
820
869
 
870
+ // For manual messages to transform
821
871
  if (messagesToTransform.length && transformer) {
822
872
  try {
823
- // for (const messageToTransform of messagesToTransform) {
824
- const transformResponse = await wrapStep(transformer({
825
- message: messagesToTransform,
826
- persona,
827
- customer: customer.id,
828
- messages,
829
- context: context
830
- }), 'transform');
831
-
832
- progress('Generated response', 'success', undefined, undefined);
833
- // Check if already had message
834
- const agentMessages = messages.filter(m => m.role === 'agent');
835
- const lastAgentMessage = agentMessages[agentMessages.length - 1];
836
- if (lastAgentMessage && lastAgentMessage.content && lastAgentMessage.content === transformResponse.message) {
837
- // Error should not have happened
838
- conversation = lockConversation(conversation, 'Duplicate message');
873
+ const transformResponse = await wrapStep(transformer({
874
+ // message: messagesToTransform,
875
+ addedMessages: messagesToTransform,
876
+ persona,
877
+ customer: customer.id,
878
+ messages,
879
+ context
880
+ }), 'transform');
881
+
882
+ progress('Generated response', 'success', undefined, undefined);
883
+
884
+ // @TODO check for duplicates, or have already sent the message
885
+ const transformedMessages =
886
+ transformResponse.messages?.length
887
+ ? transformResponse.messages
888
+ : [{ role: 'agent', content: transformResponse.message }];
889
+
890
+ for (const message of transformedMessages) {
891
+ const adjusted = {
892
+ id: idGenerator('agent'),
893
+ role: 'agent',
894
+ time: new Date().toISOString(),
895
+ ...message,
896
+ };
897
+
898
+ if (adjusted.role === 'agent' && adjusted.content && !adjusted.ignoreTransform && !adjusted.tool_calls) {
899
+ const prior = messagesToTransform.find((m) => m.id === message.id);
900
+ if (prior) {
901
+ adjusted.contentGenerated = prior.content; // BEFORE (original)
902
+ adjusted.contentTransformed = adjusted.content; // AFTER (transformed)
839
903
  } else {
840
- messages.push({
841
- id: idGenerator('agent'),
842
- role: 'agent',
843
- content: transformResponse.message,
844
- time: new Date().toISOString()
845
- });
846
- progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
904
+ // fallback if transformer changed ids
905
+ adjusted.contentGenerated = adjusted.contentGenerated ?? adjusted.content;
906
+ adjusted.contentTransformed = adjusted.contentTransformed ?? adjusted.content;
847
907
  }
848
-
849
- // }
908
+ }
909
+
910
+ if (adjusted.role === 'agent' && adjusted.content && !adjusted.ignoreTransform && !adjusted.tool_calls && !adjusted.contentTransformed) {
911
+ progress('missing contentTransformed on a generated message', 'warning', undefined, adjusted);
912
+ adjusted.contentTransformed = adjusted.content;
913
+ }
914
+
915
+ messages.push(adjusted);
916
+ progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
917
+ }
918
+
850
919
  } catch (e) {
851
920
  console.error(`Locking conversation, error transforming response: ${e.message}`);
852
921
  conversation = lockConversation(conversation, 'API: ' + e.message);
@@ -857,8 +926,8 @@ export const Spirits = {
857
926
  onStatus('transform', 'ignored');
858
927
  }
859
928
  } else {
860
- onStatus('generate', 'ignored');
861
- onStatus('transform', 'ignored');
929
+ onStatus('generate', 'ignored');
930
+ onStatus('transform', 'ignored');
862
931
  }
863
932
 
864
933
  progress('Parsing message', 'info', 'SET_PROCESSING', null);