@onereach/step-voice 7.0.30 → 7.0.32-VOIC1701.2
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/dst/Update Voice Agent.d.ts +41 -0
- package/dst/Update Voice Agent.js +183 -0
- package/dst/{Voice Agent Function Result.d.ts → Voice Agent Tool Result.d.ts } +1 -1
- package/dst/{Voice Agent Function Result.js → Voice Agent Tool Result.js } +8 -8
- package/dst/Voice Agent.js +7 -7
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import VoiceStep from './voice';
|
|
2
|
+
type SystemInstructionMode = 'append' | 'replace' | 'off';
|
|
3
|
+
interface Tool {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
parameters: string | Record<string, unknown>;
|
|
7
|
+
exitId?: string;
|
|
8
|
+
}
|
|
9
|
+
interface AgentServiceConfig {
|
|
10
|
+
provider: string;
|
|
11
|
+
model: string;
|
|
12
|
+
api_key?: string;
|
|
13
|
+
options?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
interface INPUT {
|
|
16
|
+
system_instruction_mode: SystemInstructionMode;
|
|
17
|
+
system_instruction: string;
|
|
18
|
+
developer_messages_mode: 'append' | 'replace';
|
|
19
|
+
developer_messages: Array<string | {
|
|
20
|
+
message?: string;
|
|
21
|
+
}>;
|
|
22
|
+
tools_mode: 'append' | 'replace';
|
|
23
|
+
tools: Tool[];
|
|
24
|
+
custom_config_enabled: boolean;
|
|
25
|
+
mode: string;
|
|
26
|
+
stt: Partial<AgentServiceConfig>;
|
|
27
|
+
llm: Partial<AgentServiceConfig>;
|
|
28
|
+
tts: Partial<AgentServiceConfig>;
|
|
29
|
+
realtime: Partial<AgentServiceConfig>;
|
|
30
|
+
}
|
|
31
|
+
export default class UpdateVoiceAgent extends VoiceStep<Partial<INPUT>> {
|
|
32
|
+
runStep(): Promise<void>;
|
|
33
|
+
exitToThread(): Promise<void>;
|
|
34
|
+
private findExitByLabel;
|
|
35
|
+
private normalizeMessages;
|
|
36
|
+
private buildTools;
|
|
37
|
+
private buildOptionalServiceOverride;
|
|
38
|
+
private parseAgentServiceOptions;
|
|
39
|
+
private isStepFlagEnabled;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
5
|
+
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
6
|
+
class UpdateVoiceAgent extends voice_1.default {
|
|
7
|
+
async runStep() {
|
|
8
|
+
const call = await this.fetchData();
|
|
9
|
+
this.triggers.local(`in/voice/${call.id}`, async (event) => {
|
|
10
|
+
switch (event.params.type) {
|
|
11
|
+
case 'ok': {
|
|
12
|
+
const hasTools = (this.data.tools || []).some(t => t && !lodash_1.default.isEmpty(lodash_1.default.trim(t.name)));
|
|
13
|
+
if (hasTools) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
return this.exitStep('next');
|
|
17
|
+
}
|
|
18
|
+
case 'function_call': {
|
|
19
|
+
const cb = this.thread.takeCallback();
|
|
20
|
+
const name = event.params.name ?? 'function_call';
|
|
21
|
+
const params = event.params.arguments ?? {};
|
|
22
|
+
const functionId = event.params.functionId ?? '';
|
|
23
|
+
const exitId = this.findExitByLabel(name);
|
|
24
|
+
if (exitId) {
|
|
25
|
+
this.exitStep(exitId, {
|
|
26
|
+
[name]: params,
|
|
27
|
+
name,
|
|
28
|
+
functionId,
|
|
29
|
+
__voicecb: cb,
|
|
30
|
+
callId: call.id,
|
|
31
|
+
callType: call.type,
|
|
32
|
+
callCallback: call.callback,
|
|
33
|
+
}, true);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.log.warn('Update Voice Agent: no exit for function_call', { name });
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
case 'hangup':
|
|
41
|
+
await this.handleHangup(call);
|
|
42
|
+
return await this.waitConvEnd();
|
|
43
|
+
case 'error':
|
|
44
|
+
return this.throwError(event.params.error);
|
|
45
|
+
case 'cancel':
|
|
46
|
+
return this.end();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
this.triggers.otherwise(async () => {
|
|
50
|
+
const { system_instruction_mode = 'append', system_instruction = '', developer_messages_mode = 'append', developer_messages = [], tools_mode = 'append', tools: toolDefs = [], custom_config_enabled = false, mode = '', stt = {}, llm = {}, tts = {}, realtime = {}, } = this.data;
|
|
51
|
+
const params = {};
|
|
52
|
+
if (system_instruction_mode !== 'off'
|
|
53
|
+
&& !lodash_1.default.isEmpty(lodash_1.default.trim(String(system_instruction)))) {
|
|
54
|
+
params.system_instruction = {
|
|
55
|
+
mode: system_instruction_mode === 'replace' ? 'replace' : 'append',
|
|
56
|
+
text: String(system_instruction),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const resolvedRulesMode = developer_messages_mode === 'replace' ? 'replace' : 'append';
|
|
60
|
+
const rules = this.normalizeMessages(developer_messages);
|
|
61
|
+
if (rules.length > 0 || resolvedRulesMode === 'replace') {
|
|
62
|
+
params.developer_messages = rules;
|
|
63
|
+
params.developer_messages_mode = resolvedRulesMode;
|
|
64
|
+
}
|
|
65
|
+
const resolvedToolsMode = tools_mode === 'replace' ? 'replace' : 'append';
|
|
66
|
+
const tools = this.buildTools(toolDefs);
|
|
67
|
+
if (tools.length > 0 || resolvedToolsMode === 'replace') {
|
|
68
|
+
params.tools = tools;
|
|
69
|
+
params.tools_mode = resolvedToolsMode;
|
|
70
|
+
}
|
|
71
|
+
if (this.isStepFlagEnabled(custom_config_enabled)) {
|
|
72
|
+
if (mode !== 'waterfall' && mode !== 'realtime') {
|
|
73
|
+
this.throwError(new Error(`Update Voice Agent: unknown mode "${mode}"`));
|
|
74
|
+
}
|
|
75
|
+
params.mode = mode;
|
|
76
|
+
if (mode === 'realtime') {
|
|
77
|
+
const realtimeOverride = this.buildOptionalServiceOverride('realtime', realtime);
|
|
78
|
+
if (!realtimeOverride) {
|
|
79
|
+
this.throwError(new Error('Update Voice Agent: set realtime model or options when pipeline override is enabled'));
|
|
80
|
+
}
|
|
81
|
+
params.realtime = realtimeOverride;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const sttOverride = this.buildOptionalServiceOverride('stt', stt);
|
|
85
|
+
const llmOverride = this.buildOptionalServiceOverride('llm', llm);
|
|
86
|
+
const ttsOverride = this.buildOptionalServiceOverride('tts', tts);
|
|
87
|
+
if (!sttOverride && !llmOverride && !ttsOverride) {
|
|
88
|
+
this.throwError(new Error('Update Voice Agent: set at least one model or options when pipeline override is enabled'));
|
|
89
|
+
}
|
|
90
|
+
if (sttOverride)
|
|
91
|
+
params.stt = sttOverride;
|
|
92
|
+
if (llmOverride)
|
|
93
|
+
params.llm = llmOverride;
|
|
94
|
+
if (ttsOverride)
|
|
95
|
+
params.tts = ttsOverride;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!params.system_instruction
|
|
99
|
+
&& params.developer_messages == null
|
|
100
|
+
&& params.tools == null
|
|
101
|
+
&& !params.mode) {
|
|
102
|
+
this.throwError(new Error('Update Voice Agent: provide a system instruction update, at least one rule, at least one tool, or a pipeline/models override'));
|
|
103
|
+
}
|
|
104
|
+
await this.sendCommands(call, [{ name: 'updateAgent', params }]);
|
|
105
|
+
return this.exitFlow();
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async exitToThread() {
|
|
109
|
+
const result = this.state.result;
|
|
110
|
+
await this.thread.set(`__voiceAgentContext_${this.thread.id}`, result);
|
|
111
|
+
this.thread.exitStep(this.state.exitStep, result);
|
|
112
|
+
}
|
|
113
|
+
findExitByLabel(label) {
|
|
114
|
+
const exit = lodash_1.default.find(this.step.exits, (e) => e.label === label);
|
|
115
|
+
return exit?.id;
|
|
116
|
+
}
|
|
117
|
+
normalizeMessages(messages) {
|
|
118
|
+
return (messages || [])
|
|
119
|
+
.map(item => typeof item === 'string' ? item : item?.message ?? '')
|
|
120
|
+
.map(msg => lodash_1.default.trim(String(msg)))
|
|
121
|
+
.filter(msg => !lodash_1.default.isEmpty(msg));
|
|
122
|
+
}
|
|
123
|
+
buildTools(tools) {
|
|
124
|
+
return (tools || [])
|
|
125
|
+
.filter(t => t && !lodash_1.default.isEmpty(lodash_1.default.trim(t.name)))
|
|
126
|
+
.map(t => {
|
|
127
|
+
let parameters = {};
|
|
128
|
+
if (typeof t.parameters === 'string') {
|
|
129
|
+
try {
|
|
130
|
+
parameters = JSON.parse(t.parameters) || {};
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
parameters = {};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (t.parameters && typeof t.parameters === 'object') {
|
|
137
|
+
parameters = t.parameters;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
type: 'function',
|
|
141
|
+
name: lodash_1.default.trim(t.name),
|
|
142
|
+
description: t.description || '',
|
|
143
|
+
parameters,
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
buildOptionalServiceOverride(label, service) {
|
|
148
|
+
const options = this.parseAgentServiceOptions(label, service.options);
|
|
149
|
+
const hasModel = !lodash_1.default.isEmpty(lodash_1.default.trim(String(service.model ?? '')));
|
|
150
|
+
const hasOptions = options != null && Object.keys(options).length > 0;
|
|
151
|
+
if (!hasModel && !hasOptions) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
if (lodash_1.default.isEmpty(service.provider)) {
|
|
155
|
+
this.throwError(new Error(`Update Voice Agent: provider is required for ${label} (locked from Voice Agent pipeline)`));
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
provider: service.provider ?? '',
|
|
159
|
+
model: hasModel ? lodash_1.default.trim(String(service.model)) : '',
|
|
160
|
+
options,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
parseAgentServiceOptions(label, options) {
|
|
164
|
+
if (options == null || options === '')
|
|
165
|
+
return undefined;
|
|
166
|
+
if (typeof options === 'string') {
|
|
167
|
+
try {
|
|
168
|
+
options = JSON.parse(options);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
this.throwError(new Error(`Update Voice Agent: invalid options JSON for ${label}`));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (typeof options !== 'object' || Array.isArray(options)) {
|
|
175
|
+
this.throwError(new Error(`Update Voice Agent: options for ${label} must be a JSON object`));
|
|
176
|
+
}
|
|
177
|
+
return options;
|
|
178
|
+
}
|
|
179
|
+
isStepFlagEnabled(value) {
|
|
180
|
+
return value === true || value === 'true' || value === 1 || value === '1';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.default = UpdateVoiceAgent;
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const voice_1 = tslib_1.__importDefault(require("./voice"));
|
|
5
|
-
class
|
|
5
|
+
class VoiceAgentToolResult extends voice_1.default {
|
|
6
6
|
async runStep() {
|
|
7
7
|
const { result, stopAgent } = this.data;
|
|
8
8
|
const ctx = await this.thread.get(`__voiceAgentContext_${this.thread.id}`);
|
|
9
9
|
if (!ctx?.callId) {
|
|
10
|
-
throw new Error('Voice Agent
|
|
10
|
+
throw new Error('Voice Agent Tool Result: missing call context (must be placed on a Voice Agent tool exit)');
|
|
11
11
|
}
|
|
12
|
-
const { callId, callCallback, name:
|
|
13
|
-
this.log.info(
|
|
12
|
+
const { callId, callCallback, name: toolName, toolCallId } = ctx;
|
|
13
|
+
this.log.info('Voice Agent Tool Result', { toolCallId, callId, threadId: this.thread.id });
|
|
14
14
|
const params = {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
toolName,
|
|
16
|
+
toolCallId,
|
|
17
17
|
result,
|
|
18
18
|
options: { stop: stopAgent }
|
|
19
19
|
};
|
|
@@ -22,7 +22,7 @@ class VoiceAgentFunctionResult extends voice_1.default {
|
|
|
22
22
|
name: 'out/voice/voicer',
|
|
23
23
|
params: {
|
|
24
24
|
id: callId,
|
|
25
|
-
commands: [{ name: '
|
|
25
|
+
commands: [{ name: 'agentToolResult', params }]
|
|
26
26
|
}
|
|
27
27
|
}, {
|
|
28
28
|
target: callCallback,
|
|
@@ -32,4 +32,4 @@ class VoiceAgentFunctionResult extends voice_1.default {
|
|
|
32
32
|
this.exitStep('next');
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
exports.default =
|
|
35
|
+
exports.default = VoiceAgentToolResult;
|
package/dst/Voice Agent.js
CHANGED
|
@@ -8,19 +8,19 @@ class VoiceAgent extends voice_1.default {
|
|
|
8
8
|
const call = await this.fetchData();
|
|
9
9
|
this.triggers.local(`in/voice/${call.id}`, async (event) => {
|
|
10
10
|
switch (event.params.type) {
|
|
11
|
-
case '
|
|
12
|
-
if (event.params.type !== '
|
|
11
|
+
case 'tool_call': {
|
|
12
|
+
if (event.params.type !== 'tool_call')
|
|
13
13
|
return;
|
|
14
14
|
const cb = this.thread.takeCallback();
|
|
15
|
-
const name = event.params.name ?? '
|
|
15
|
+
const name = event.params.name ?? 'tool_call';
|
|
16
16
|
const params = event.params.arguments ?? {};
|
|
17
|
-
const
|
|
18
|
-
const exitId = this.findExitByLabel(name) ?? this.getExitStepId('
|
|
17
|
+
const toolCallId = event.params.toolCallId ?? '';
|
|
18
|
+
const exitId = this.findExitByLabel(name) ?? this.getExitStepId('tool_call');
|
|
19
19
|
if (exitId) {
|
|
20
20
|
this.exitStep(exitId, {
|
|
21
21
|
[name]: params,
|
|
22
22
|
name,
|
|
23
|
-
|
|
23
|
+
toolCallId,
|
|
24
24
|
__voicecb: cb,
|
|
25
25
|
callId: call.id,
|
|
26
26
|
callType: call.type,
|
|
@@ -28,7 +28,7 @@ class VoiceAgent extends voice_1.default {
|
|
|
28
28
|
}, true);
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
|
-
this.log.warn('no exit for
|
|
31
|
+
this.log.warn('no exit for tool_call', { name });
|
|
32
32
|
}
|
|
33
33
|
return;
|
|
34
34
|
}
|