@scout9/app 1.0.0-alpha.0.5.8 → 1.0.0-alpha.0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/public.d.ts CHANGED
@@ -359,6 +359,12 @@ export type Agent = {
359
359
  model?: ("Scout9" | "bard" | "openai");
360
360
  transcripts?: Message[][] | undefined;
361
361
  audios?: any[] | undefined;
362
+ pmt?: {
363
+ tag?: string;
364
+ ingress: "auto" | "manual" | "app" | "webhook";
365
+ llm?: string;
366
+ scout9?: string;
367
+ }
362
368
  };
363
369
 
364
370
  export type AgentConfiguration = Agent & {id: string};
@@ -537,6 +543,14 @@ export type IntentWorkflowEvent = {
537
543
  initial: string | null;
538
544
  };
539
545
 
546
+ export type MessageEntity = {
547
+ start: number;
548
+ end: number;
549
+ type: string;
550
+ option?: string | null;
551
+ text?: string | null;
552
+ }
553
+
540
554
  export type Message = {
541
555
  /** Unique ID for the message */
542
556
  id: string;
@@ -555,6 +569,8 @@ export type Message = {
555
569
  intentScore?: (number | null) | undefined;
556
570
  /** How long to delay the message manually in seconds */
557
571
  delayInSeconds?: (number | null) | undefined;
572
+ /** Entities related to the message */
573
+ entities?: MessageEntity[] | null;
558
574
  };
559
575
 
560
576
  export type PersonaConfiguration = AgentConfiguration;
@@ -630,7 +646,7 @@ export type WorkflowEvent = {
630
646
  conversation: Conversation;
631
647
  context?: any;
632
648
  message: Message;
633
- agent: Omit<AgentConfiguration, 'transcripts' | 'audios' | 'includedLocations' | 'excludedLocations' | 'model' | 'context'>;
649
+ agent: Omit<AgentConfiguration, 'transcripts' | 'audios' | 'includedLocations' | 'excludedLocations' | 'model' | 'context' | 'pmt'>;
634
650
  customer: Customer;
635
651
  intent: IntentWorkflowEvent;
636
652
  stagnationCount: number;
@@ -657,7 +673,7 @@ export type WorkflowResponseSlotBase = {
657
673
  forwardNote?: string | undefined;
658
674
  instructions?: Instruction[] | undefined;
659
675
  removeInstructions?: string[] | undefined;
660
- message?: string | undefined;
676
+ message?: string | {content: string; transform?: boolean} | undefined;
661
677
  secondsDelay?: number | undefined;
662
678
  scheduled?: number | undefined;
663
679
  contextUpsert?: {
@@ -698,7 +714,6 @@ export type WorkflowResponseMessageApiResponse = string | {
698
714
  };
699
715
  };
700
716
 
701
-
702
717
  export type WorkflowsConfiguration = {
703
718
  /** Workflow id association, used to handle route params */
704
719
  entities: string[];
@@ -1,6 +1,14 @@
1
1
  import { z } from 'zod';
2
2
  import { zId } from './utils.js';
3
3
 
4
+ export const MessageEntitySchema = z.object({
5
+ start: z.number(),
6
+ end: z.number(),
7
+ type: z.string(),
8
+ option: z.string().optional().nullable(),
9
+ text: z.string().optional().nullable()
10
+ });
11
+
4
12
  export const MessageSchema = z.object({
5
13
  id: zId('Message ID', {description: 'Unique ID for the message'}),
6
14
  role: z.enum(['agent', 'customer', 'system']),
@@ -11,5 +19,6 @@ export const MessageSchema = z.object({
11
19
  context: z.any({description: 'The context generated from the message'}).optional(),
12
20
  intent: z.string({description: 'Detected intent'}).optional().nullable(),
13
21
  intentScore: z.number({description: 'Confidence score of the assigned intent'}).nullable().optional(),
14
- delayInSeconds: z.number({description: 'How long to delay the message manually in seconds'}).nullable().optional()
22
+ delayInSeconds: z.number({description: 'How long to delay the message manually in seconds'}).nullable().optional(),
23
+ entities: z.array(MessageEntitySchema).optional().nullable()
15
24
  });
@@ -45,7 +45,15 @@ export const AgentSchema = z.object({
45
45
  excludedLocations: z.array(z.string({description: 'Locations the agent is excluded from'})).optional(),
46
46
  model: z.enum(['Scout9', 'bard', 'openai']).optional().default('openai'),
47
47
  transcripts: z.array(z.array(MessageSchema)).optional(),
48
- audios: z.array(z.any()).optional()
48
+ audios: z.array(z.any()).optional(),
49
+ pmt: z.object({
50
+ tag: z.string().optional(),
51
+ ingress: z.enum(["auto", "manual", "app", "workflow"]),
52
+ llm: z.string().optional(),
53
+ webhookUri: z.string().optional(),
54
+ watermarkEnabled: z.boolean().optional(),
55
+ watermark: z.string().optional()
56
+ }).optional()
49
57
  });
50
58
 
51
59
  export const PersonaSchema = AgentSchema;
@@ -134,7 +134,8 @@ export const WorkflowEventSchema = z.object({
134
134
  includedLocations: true,
135
135
  excludedLocations: true,
136
136
  model: true,
137
- context: true
137
+ context: true,
138
+ pmt: true
138
139
  }),
139
140
  customer: CustomerSchema,
140
141
  intent: IntentWorkflowEventSchema,
@@ -151,7 +152,10 @@ export const WorkflowResponseSlotBaseSchema = z.object({
151
152
  .optional(),
152
153
  instructions: InstructionSchema.optional(),
153
154
  removeInstructions: z.array(z.string()).optional(),
154
- message: z.string().optional(),
155
+ message: z.union([z.string(), z.object({
156
+ content: z.string(),
157
+ transform: z.boolean().optional()
158
+ })]).optional(),
155
159
  secondsDelay: z.number().optional(),
156
160
  scheduled: z.number().optional(),
157
161
  contextUpsert: ConversationContext.optional(),
@@ -19,6 +19,7 @@
19
19
  * @property {Array<import('@scout9/app').Message>} messages
20
20
  * @property {import('@scout9/app').Message} message - the message sent by the customer (should exist in messages)
21
21
  * @property {import('@scout9/app').Customer} customer
22
+ * @property {import('@scout9/app').ConversationProgress} progress - progress checklist for manual/auto ingress workflows (needed if conversation progress is not managed by external webhooks or @scout9 apps (ingress app/webhook)
22
23
  * @property {any} context
23
24
  */
24
25
 
@@ -46,6 +47,14 @@
46
47
  * @property {any} context
47
48
  */
48
49
 
50
+ /**
51
+ * @typedef {Object} GenerateOutput
52
+ * @property {import('@scout9/admin').GenerateResponse | undefined} generate
53
+ * @property {Array<import('@scout9/app').Message>} messages
54
+ * @property {import('@scout9/app').Conversation} conversation
55
+ * @property {any} context
56
+ */
57
+
49
58
  /**
50
59
  * @callback ParseFun
51
60
  * @param {string} message - message to send
@@ -65,11 +74,18 @@
65
74
  * @returns {Promise<import('@scout9/admin').GenerateResponse>}
66
75
  */
67
76
 
77
+ /**
78
+ * @callback TransformerFun
79
+ * @param {import('@scout9/admin').PmtTransformRequest} data - data to generate from
80
+ * @returns {Promise<import('@scout9/admin').PmtTransformResponse>}
81
+ */
82
+
68
83
  /**
69
84
  * @callback IdGeneratorFun
70
85
  * @param {import('@scout9/app').Message['role']} prefix
71
86
  * @returns {string}
72
87
  */
88
+
73
89
  /**
74
90
  * @callback StatusCallback
75
91
  * @param {string} message
@@ -84,6 +100,7 @@
84
100
  * @property {ParseFun} parser
85
101
  * @property {WorkflowFun} workflow
86
102
  * @property {GenerateFun} generator
103
+ * @property {TransformerFun} transformer
87
104
  * @property {IdGeneratorFun} idGenerator
88
105
  * @property {StatusCallback | undefined} [progress]
89
106
  */
@@ -110,6 +127,7 @@ export const Spirits = {
110
127
  parser,
111
128
  workflow,
112
129
  generator,
130
+ transformer,
113
131
  idGenerator,
114
132
  progress = (message, level, type, payload) => {
115
133
  },
@@ -265,6 +283,7 @@ export const Spirits = {
265
283
  message.intentScore = parsePayload.intentScore;
266
284
  }
267
285
  message.context = parsePayload.context;
286
+ message.entities = parsePayload.entities;
268
287
  const index = messages.findIndex(m => m.content === message.content || m.id === message.id);
269
288
  if (index === -1) {
270
289
  const _message = {
@@ -272,6 +291,7 @@ export const Spirits = {
272
291
  role: 'customer',
273
292
  content: message,
274
293
  context: parsePayload.context,
294
+ entities: parsePayload.entities,
275
295
  time: new Date().toISOString()
276
296
  };
277
297
  if (parsePayload.intent) {
@@ -285,6 +305,7 @@ export const Spirits = {
285
305
  progress('Added message', 'info', 'ADD_MESSAGE', _message);
286
306
  } else {
287
307
  messages[index].context = parsePayload.context;
308
+ messages[index].entities = parsePayload.entities;
288
309
  if (parsePayload.intent) {
289
310
  messages[index].intent = parsePayload.intent;
290
311
  }
@@ -349,6 +370,7 @@ export const Spirits = {
349
370
  }, []));
350
371
  const hasNoInstructions = slots.every(s => !s.instructions || (Array.isArray(s.instructions) && s.instructions.length === 0));
351
372
  const hasNoCustomMessage = slots.every(s => !s.message);
373
+ const messagesToTransform = slots.filter(s => !!s.message && typeof s.message === 'object' && !!s.message.transform);
352
374
  const previousLockAttempt = conversation.lockAttempts || 0; // Used to track
353
375
 
354
376
  if (hasNoInstructions && noNewContext) {
@@ -596,6 +618,43 @@ export const Spirits = {
596
618
  conversation = lockConversation(conversation, 'API: ' + e.message);
597
619
  }
598
620
  }
621
+
622
+ if (messagesToTransform.length && transformer) {
623
+ try {
624
+ for (const messageToTransform of messagesToTransform) {
625
+ const transformResponse = await transformer({
626
+ message: messagesToTransform,
627
+ persona,
628
+ customer: customer.id,
629
+ messages,
630
+ context: context
631
+ });
632
+
633
+ progress('Generated response', 'success', undefined, undefined);
634
+ // Check if already had message
635
+ const agentMessages = messages.filter(m => m.role === 'agent');
636
+ const lastAgentMessage = agentMessages[agentMessages.length - 1];
637
+ if (lastAgentMessage && lastAgentMessage.content === transformResponse.message) {
638
+ // Error should not have happened
639
+ conversation = lockConversation(conversation, 'Duplicate message');
640
+ } else {
641
+ messages.push({
642
+ id: idGenerator('agent'),
643
+ role: 'agent',
644
+ content: transformResponse.message,
645
+ time: new Date().toISOString()
646
+ });
647
+ progress('Added agent message', 'info', 'ADD_MESSAGE', messages[messages.length - 1]);
648
+ }
649
+
650
+ }
651
+ } catch (e) {
652
+ console.error(`Locking conversation, error transforming response: ${e.message}`);
653
+ conversation = lockConversation(conversation, 'API: ' + e.message);
654
+ }
655
+ } else if (messagesToTransform.length) {
656
+ console.warn(`No transformer provided`)
657
+ }
599
658
  }
600
659
 
601
660
  progress('Parsing message', 'info', 'SET_PROCESSING', null);