@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/dist/{dev-ccf05f24.cjs → dev-32a9a0c8.cjs} +155 -9
- package/dist/{index-b329d3e5.cjs → index-d94326d3.cjs} +7 -7
- package/dist/index.cjs +4 -4
- package/dist/{macros-f855de63.cjs → macros-621210f1.cjs} +25 -4
- package/dist/{multipart-parser-5819fcfd.cjs → multipart-parser-6ba4e92d.cjs} +4 -4
- package/dist/schemas.cjs +2 -1
- package/dist/{spirits-2ab4d673.cjs → spirits-8819b1c9.cjs} +173 -78
- package/dist/spirits.cjs +1 -1
- package/dist/testing-tools.cjs +3 -3
- package/package.json +2 -1
- package/src/core/templates/app.js +277 -178
- package/src/public.d.ts +18 -3
- package/src/runtime/schemas/message.js +10 -1
- package/src/runtime/schemas/users.js +9 -1
- package/src/runtime/schemas/workflow.js +6 -2
- package/src/testing-tools/spirits.js +59 -0
- package/types/index.d.ts +1974 -164
- package/types/index.d.ts.map +3 -1
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().
|
|
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);
|