@scout9/app 1.0.0-alpha.0.9.8 → 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-a94c40fe.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-a94c40fe.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-27956169.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-d5ac17af.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-d5ac17af.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-d5ac17af.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-d5ac17af.cjs");
6
- var dev = require("./dev-a94c40fe.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-d5ac17af.cjs");
5
+ var index = require("./index-17797705.cjs");
6
6
  require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
7
- require("./dev-a94c40fe.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'
@@ -1054,8 +1080,11 @@ var Spirits = {
1054
1080
  try {
1055
1081
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1056
1082
  newMessage = _step3.value;
1057
- messages.push(newMessage);
1058
- 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]);
1059
1088
  }
1060
1089
  } catch (err) {
1061
1090
  _iterator3.e(err);
@@ -1073,82 +1102,128 @@ var Spirits = {
1073
1102
  }
1074
1103
  }
1075
1104
  }
1076
- _context4.next = 176;
1105
+ _context5.next = 160;
1077
1106
  break;
1078
- case 171:
1079
- _context4.prev = 171;
1080
- _context4.t5 = _context4["catch"](161);
1081
- onError(_context4.t5);
1082
- console.error("Spirits: Locking conversation, error generating response: ".concat(_context4.t5.message));
1083
- conversation = lockConversation(conversation, 'API: ' + _context4.t5.message);
1084
- case 176:
1085
- _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;
1086
1115
  break;
1087
- case 178:
1116
+ case 162:
1088
1117
  onStatus('generate', 'ignored');
1089
- case 179:
1118
+ case 163:
1090
1119
  if (!(messagesToTransform.length && transformer)) {
1091
- _context4.next = 197;
1120
+ _context5.next = 195;
1092
1121
  break;
1093
1122
  }
1094
- _context4.prev = 180;
1095
- _context4.next = 183;
1123
+ _context5.prev = 164;
1124
+ _context5.next = 167;
1096
1125
  return wrapStep(transformer({
1097
- message: messagesToTransform,
1126
+ // message: messagesToTransform,
1127
+ addedMessages: messagesToTransform,
1098
1128
  persona: persona,
1099
1129
  customer: customer.id,
1100
1130
  messages: messages,
1101
1131
  context: context
1102
1132
  }), 'transform');
1103
- case 183:
1104
- transformResponse = _context4.sent;
1133
+ case 167:
1134
+ transformResponse = _context5.sent;
1105
1135
  progress('Generated response', 'success', undefined, undefined);
1106
- // Check if already had message
1107
- _agentMessages = messages.filter(function (m) {
1108
- 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);
1109
1179
  });
1110
- _lastAgentMessage = _agentMessages[_agentMessages.length - 1];
1111
- if (_lastAgentMessage && _lastAgentMessage.content && _lastAgentMessage.content === transformResponse.message) {
1112
- // Error should not have happened
1113
- conversation = lockConversation(conversation, 'Duplicate message');
1114
- } else {
1115
- messages.push({
1116
- id: idGenerator('agent'),
1117
- role: 'agent',
1118
- content: transformResponse.message,
1119
- contentTransformed: transformResponse.message,
1120
- contentGenerated: messagesToTransform,
1121
- time: new Date().toISOString()
1122
- });
1123
- 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;
1124
1185
  }
1125
-
1126
- // }
1127
- _context4.next = 195;
1186
+ return _context5.delegateYield(_loop(), "t6", 176);
1187
+ case 176:
1188
+ _context5.next = 174;
1128
1189
  break;
1129
- case 190:
1130
- _context4.prev = 190;
1131
- _context4.t6 = _context4["catch"](180);
1132
- console.error("Locking conversation, error transforming response: ".concat(_context4.t6.message));
1133
- conversation = lockConversation(conversation, 'API: ' + _context4.t6.message);
1134
- onError(_context4.t6);
1135
- case 195:
1136
- _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;
1137
1212
  break;
1138
- case 197:
1213
+ case 195:
1139
1214
  if (messagesToTransform.length) {
1140
1215
  console.warn("No transformer provided");
1141
1216
  onStatus('transform', 'ignored');
1142
1217
  }
1143
- case 198:
1144
- _context4.next = 202;
1218
+ case 196:
1219
+ _context5.next = 200;
1145
1220
  break;
1146
- case 200:
1221
+ case 198:
1147
1222
  onStatus('generate', 'ignored');
1148
1223
  onStatus('transform', 'ignored');
1149
- case 202:
1224
+ case 200:
1150
1225
  progress('Parsing message', 'info', 'SET_PROCESSING', null);
1151
- return _context4.abrupt("return", {
1226
+ return _context5.abrupt("return", {
1152
1227
  conversation: {
1153
1228
  before: conversationBefore,
1154
1229
  after: conversation,
@@ -1170,11 +1245,11 @@ var Spirits = {
1170
1245
  followup: followup,
1171
1246
  entityContextUpsert: entityContextUpsert
1172
1247
  });
1173
- case 204:
1248
+ case 202:
1174
1249
  case "end":
1175
- return _context4.stop();
1250
+ return _context5.stop();
1176
1251
  }
1177
- }, _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]]);
1178
1253
  }));
1179
1254
  function customer(_x) {
1180
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-a94c40fe.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.8",
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);
@@ -787,13 +834,14 @@ export const Spirits = {
787
834
  ).items;
788
835
 
789
836
 
790
- if (lastAgentMessage && lastAgentMessage.content && addedMessages.some((message) => message.content === lastAgentMessage.content)) {
837
+ if (lastAgentMessage && lastAgentMessage.content && addedMessages.some((message) => message.content === lastAgentMessage.content)) {
791
838
  // Error should not have happened
792
839
  conversation = lockConversation(conversation, 'Duplicate message');
793
840
  } else {
794
841
  for (const newMessage of addedMessages) {
795
- messages.push(newMessage);
796
- 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]);
797
845
  }
798
846
  }
799
847
 
@@ -819,37 +867,55 @@ export const Spirits = {
819
867
  onStatus('generate', 'ignored');
820
868
  }
821
869
 
870
+ // For manual messages to transform
822
871
  if (messagesToTransform.length && transformer) {
823
872
  try {
824
- // for (const messageToTransform of messagesToTransform) {
825
- const transformResponse = await wrapStep(transformer({
826
- message: messagesToTransform,
827
- persona,
828
- customer: customer.id,
829
- messages,
830
- context: context
831
- }), 'transform');
832
-
833
- progress('Generated response', 'success', undefined, undefined);
834
- // Check if already had message
835
- const agentMessages = messages.filter(m => m.role === 'agent');
836
- const lastAgentMessage = agentMessages[agentMessages.length - 1];
837
- if (lastAgentMessage && lastAgentMessage.content && lastAgentMessage.content === transformResponse.message) {
838
- // Error should not have happened
839
- 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)
840
903
  } else {
841
- messages.push({
842
- id: idGenerator('agent'),
843
- role: 'agent',
844
- content: transformResponse.message,
845
- contentTransformed: transformResponse.message,
846
- contentGenerated: messagesToTransform,
847
- time: new Date().toISOString()
848
- });
849
- 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;
850
907
  }
851
-
852
- // }
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
+
853
919
  } catch (e) {
854
920
  console.error(`Locking conversation, error transforming response: ${e.message}`);
855
921
  conversation = lockConversation(conversation, 'API: ' + e.message);
@@ -860,8 +926,8 @@ export const Spirits = {
860
926
  onStatus('transform', 'ignored');
861
927
  }
862
928
  } else {
863
- onStatus('generate', 'ignored');
864
- onStatus('transform', 'ignored');
929
+ onStatus('generate', 'ignored');
930
+ onStatus('transform', 'ignored');
865
931
  }
866
932
 
867
933
  progress('Parsing message', 'info', 'SET_PROCESSING', null);