@scout9/app 1.0.0-alpha.0.8.9 → 1.0.0-alpha.0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dev = require("./dev-c58715b1.cjs");
6
- require("./_rollupPluginBabelHelpers-606d8129.cjs");
5
+ var dev = require("./dev-9a3ac888.cjs");
6
+ require("./_rollupPluginBabelHelpers-9c73c95c.cjs");
7
7
  require('util');
8
8
  require('stream');
9
9
  require('path');
@@ -24,7 +24,7 @@ require('node:url');
24
24
  require('node:events');
25
25
  require('node:stream');
26
26
  require('node:string_decoder');
27
- require("./macros-9ad79144.cjs");
27
+ require("./macros-77983cef.cjs");
28
28
  require('node:readline');
29
29
  require('node:process');
30
30
  require('node:os');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scout9/app",
3
- "version": "1.0.0-alpha.0.8.9",
3
+ "version": "1.0.0-alpha.0.9.1",
4
4
  "description": "Build and deploy your Scout9 app for SMS auto replies",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -104,6 +104,40 @@
104
104
  */
105
105
 
106
106
 
107
+ class SpiritError extends Error {
108
+ /**
109
+ * @param {string} message - Description of the error.
110
+ * @param {string} step - The step or phase in which the error occurred.
111
+ */
112
+ constructor(message, step) {
113
+ super(message);
114
+ this.name = this.constructor.name;
115
+ this.step = step;
116
+
117
+ // Ensures the stack trace starts from where this error was created
118
+ if (Error.captureStackTrace) {
119
+ Error.captureStackTrace(this, this.constructor);
120
+ }
121
+ }
122
+
123
+ /**
124
+ *
125
+ * @param {unknown} err
126
+ * @param {string} step
127
+ * @returns {SpiritError}
128
+ */
129
+ static fromError(err, step) {
130
+ if (err instanceof SpiritError) return err;
131
+ if (err instanceof Error) {
132
+ const wrapped = new SpiritError(err.message, step, { cause: err });
133
+ wrapped.stack = err.stack;
134
+ return wrapped;
135
+ }
136
+ // fallback for non-Error values
137
+ return new SpiritError(String(err), step);
138
+ }
139
+ }
140
+
107
141
  /**
108
142
  * @typedef {Object} ConversationEvent
109
143
  * @property {(Change<import('@scout9/app').Conversation> & {
@@ -258,6 +292,25 @@ export const Spirits = {
258
292
  }
259
293
  };
260
294
 
295
+ const onStatus = (statusType, completeOrError = true) => {
296
+ progress(`${statusType}: ${completeOrError}`, 'info', 'STATUS', {[statusType]: completeOrError});
297
+ }
298
+
299
+ /**
300
+ * @param {Promise<any>} prom
301
+ * @param {string} step
302
+ */
303
+ const wrapStep = async (prom, step) => {
304
+ try {
305
+ const result = await prom;
306
+ onStatus(step);
307
+ return result;
308
+ } catch (error) {
309
+ onStatus(step, error.message || 'UNHANDLED ERROR');
310
+ throw SpiritError.fromError(error, step);
311
+ }
312
+ }
313
+
261
314
  // 1. Check inputs
262
315
  if (!conversation.$agent) {
263
316
  throw new Error(`SpiritsError: No agent found in conversation, must define ".$agent" in the conversation`);
@@ -284,7 +337,8 @@ export const Spirits = {
284
337
 
285
338
  // 2. Parse the message
286
339
  progress('Parsing message', 'info', 'SET_PROCESSING', 'user');
287
- const parsePayload = await parser(message.content, 'en');
340
+ const parsePayload = await wrapStep(parser(message.content, 'en'), 'parse');
341
+
288
342
  if (parsePayload.intent) {
289
343
  message.intent = parsePayload.intent;
290
344
  }
@@ -370,7 +424,7 @@ export const Spirits = {
370
424
 
371
425
  // 3. Run the contextualizer
372
426
  progress('Running contextualizer', 'info', 'SET_PROCESSING', 'system');
373
- const newContextMessages = await contextualizer({ conversation, messages });
427
+ const newContextMessages = await wrapStep(contextualizer({ conversation, messages }), 'contextualize');
374
428
  for (const contextMessage of newContextMessages) {
375
429
  if (!messages.find(mes => mes.content === contextMessage.content)) {
376
430
  messages.push(contextMessage);
@@ -383,7 +437,7 @@ export const Spirits = {
383
437
  // 4. Run the workflow
384
438
  progress('Running workflow', 'info', 'SET_PROCESSING', 'system');
385
439
 
386
- const slots = await workflow({
440
+ const slots = await wrapStep(workflow({
387
441
  messages,
388
442
  conversation,
389
443
  context,
@@ -396,7 +450,7 @@ export const Spirits = {
396
450
  initial: conversation.intent || null
397
451
  },
398
452
  stagnationCount: conversation.lockAttempts || 0
399
- })
453
+ }), 'workflow')
400
454
  .then((res) => Array.isArray(res) ? res : [res])
401
455
  .then((slots) => slots.reduce((accumulator, slot) => {
402
456
  if ('toJSON' in slot) {
@@ -646,7 +700,7 @@ export const Spirits = {
646
700
  if (!!_tasks && Array.isArray(_tasks) && !!_tasks.length) {
647
701
  generatorInput.tasks = _tasks;
648
702
  }
649
- const generatorPayload = await generator(generatorInput);
703
+ const generatorPayload = await wrapStep(generator(generatorInput), 'generate');
650
704
  if (!generatorPayload.send) {
651
705
  progress(
652
706
  'Generated response',
@@ -710,10 +764,12 @@ export const Spirits = {
710
764
  // De-dupe by content (change the key if you want stricter uniqueness)
711
765
  .reduce(
712
766
  (acc, msg) => {
713
- const key = String(msg.content); // e.g. `${msg.role}::${msg.content}` for stronger uniqueness
767
+ const key = String(msg.content || msg.tool_calls ? JSON.stringify(msg.tool_calls) : ''); // e.g. `${msg.role}::${msg.content}` for stronger uniqueness
714
768
  if (!acc.seen.has(key)) {
715
769
  acc.seen.add(key);
716
770
  acc.items.push(msg);
771
+ } else {
772
+ console.warn(`Duplicate message removed: ${JSON.stringify(msg)}`);
717
773
  }
718
774
  return acc;
719
775
  },
@@ -749,18 +805,20 @@ export const Spirits = {
749
805
  console.error(`Spirits: Locking conversation, error generating response: ${e.message}`);
750
806
  conversation = lockConversation(conversation, 'API: ' + e.message);
751
807
  }
808
+ } else {
809
+ onStatus('generate', 'ignored');
752
810
  }
753
811
 
754
812
  if (messagesToTransform.length && transformer) {
755
813
  try {
756
- for (const messageToTransform of messagesToTransform) {
757
- const transformResponse = await transformer({
814
+ // for (const messageToTransform of messagesToTransform) {
815
+ const transformResponse = await wrapStep(transformer({
758
816
  message: messagesToTransform,
759
817
  persona,
760
818
  customer: customer.id,
761
819
  messages,
762
820
  context: context
763
- });
821
+ }), 'transform');
764
822
 
765
823
  progress('Generated response', 'success', undefined, undefined);
766
824
  // Check if already had message
@@ -779,7 +837,7 @@ export const Spirits = {
779
837
  progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
780
838
  }
781
839
 
782
- }
840
+ // }
783
841
  } catch (e) {
784
842
  console.error(`Locking conversation, error transforming response: ${e.message}`);
785
843
  conversation = lockConversation(conversation, 'API: ' + e.message);
@@ -787,7 +845,11 @@ export const Spirits = {
787
845
  }
788
846
  } else if (messagesToTransform.length) {
789
847
  console.warn(`No transformer provided`);
848
+ onStatus('transform', 'ignored');
790
849
  }
850
+ } else {
851
+ onStatus('generate', 'ignored');
852
+ onStatus('transform', 'ignored');
791
853
  }
792
854
 
793
855
  progress('Parsing message', 'info', 'SET_PROCESSING', null);