@teamlearners/clawops 0.23.0 → 0.25.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/agent/index.cjs +151 -680
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +4 -328
- package/dist/agent/index.d.ts +4 -328
- package/dist/agent/index.js +55 -615
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/livekit/index.cjs +496 -0
- package/dist/agent/livekit/index.cjs.map +1 -0
- package/dist/agent/livekit/index.d.cts +172 -0
- package/dist/agent/livekit/index.d.ts +172 -0
- package/dist/agent/livekit/index.js +490 -0
- package/dist/agent/livekit/index.js.map +1 -0
- package/dist/base-Cje1TDJi.d.cts +355 -0
- package/dist/base-Cje1TDJi.d.ts +355 -0
- package/dist/chunk-2BAYUQ7O.js +610 -0
- package/dist/chunk-2BAYUQ7O.js.map +1 -0
- package/dist/{chunk-NXMTLS2U.cjs → chunk-IVJXHNUN.cjs} +3 -3
- package/dist/{chunk-NXMTLS2U.cjs.map → chunk-IVJXHNUN.cjs.map} +1 -1
- package/dist/{chunk-JU36ASTU.js → chunk-THZNZBP2.js} +3 -3
- package/dist/{chunk-JU36ASTU.js.map → chunk-THZNZBP2.js.map} +1 -1
- package/dist/chunk-U4UFTVLX.cjs +631 -0
- package/dist/chunk-U4UFTVLX.cjs.map +1 -0
- package/dist/index.cjs +52 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +19 -3
- package/dist/index.js.map +1 -1
- package/package.json +14 -1
package/dist/agent/index.js
CHANGED
|
@@ -1,359 +1,10 @@
|
|
|
1
|
-
import { DEFAULT_BASE_URL, AgentError, AgentConnectionError, VERSION } from '../chunk-
|
|
2
|
-
import
|
|
1
|
+
import { DEFAULT_BASE_URL, AgentError, AgentConnectionError, VERSION } from '../chunk-THZNZBP2.js';
|
|
2
|
+
import { NOOP_LOGGER, resolveBuiltinTools, createAgentLogger, createPipelineLogger, BufferingCall, attachBuffered, ulawToPcm16, resamplePcm16, getBuiltinToolSchemas, BUILTIN_TOOL_NAMES, executeBuiltinTool, pcm16ToUlaw, applyUlawGain } from '../chunk-2BAYUQ7O.js';
|
|
3
|
+
export { BUILTIN_TOOL_NAMES, BuiltinTool, DECODE_TABLE, createAgentLogger, createPipelineLogger, executeBuiltinTool, getBuiltinToolSchemas, isBuiltinTool, pcm16ToUlaw, resamplePcm16, ulawToPcm16 } from '../chunk-2BAYUQ7O.js';
|
|
3
4
|
import * as fs from 'fs';
|
|
4
5
|
import * as path from 'path';
|
|
5
6
|
import os from 'os';
|
|
6
7
|
|
|
7
|
-
// src/agent/audio.ts
|
|
8
|
-
var _BIAS = 132;
|
|
9
|
-
var _CLIP = 32635;
|
|
10
|
-
var DECODE_TABLE = [
|
|
11
|
-
-32124,
|
|
12
|
-
-31100,
|
|
13
|
-
-30076,
|
|
14
|
-
-29052,
|
|
15
|
-
-28028,
|
|
16
|
-
-27004,
|
|
17
|
-
-25980,
|
|
18
|
-
-24956,
|
|
19
|
-
-23932,
|
|
20
|
-
-22908,
|
|
21
|
-
-21884,
|
|
22
|
-
-20860,
|
|
23
|
-
-19836,
|
|
24
|
-
-18812,
|
|
25
|
-
-17788,
|
|
26
|
-
-16764,
|
|
27
|
-
-15996,
|
|
28
|
-
-15484,
|
|
29
|
-
-14972,
|
|
30
|
-
-14460,
|
|
31
|
-
-13948,
|
|
32
|
-
-13436,
|
|
33
|
-
-12924,
|
|
34
|
-
-12412,
|
|
35
|
-
-11900,
|
|
36
|
-
-11388,
|
|
37
|
-
-10876,
|
|
38
|
-
-10364,
|
|
39
|
-
-9852,
|
|
40
|
-
-9340,
|
|
41
|
-
-8828,
|
|
42
|
-
-8316,
|
|
43
|
-
-7932,
|
|
44
|
-
-7676,
|
|
45
|
-
-7420,
|
|
46
|
-
-7164,
|
|
47
|
-
-6908,
|
|
48
|
-
-6652,
|
|
49
|
-
-6396,
|
|
50
|
-
-6140,
|
|
51
|
-
-5884,
|
|
52
|
-
-5628,
|
|
53
|
-
-5372,
|
|
54
|
-
-5116,
|
|
55
|
-
-4860,
|
|
56
|
-
-4604,
|
|
57
|
-
-4348,
|
|
58
|
-
-4092,
|
|
59
|
-
-3900,
|
|
60
|
-
-3772,
|
|
61
|
-
-3644,
|
|
62
|
-
-3516,
|
|
63
|
-
-3388,
|
|
64
|
-
-3260,
|
|
65
|
-
-3132,
|
|
66
|
-
-3004,
|
|
67
|
-
-2876,
|
|
68
|
-
-2748,
|
|
69
|
-
-2620,
|
|
70
|
-
-2492,
|
|
71
|
-
-2364,
|
|
72
|
-
-2236,
|
|
73
|
-
-2108,
|
|
74
|
-
-1980,
|
|
75
|
-
-1884,
|
|
76
|
-
-1820,
|
|
77
|
-
-1756,
|
|
78
|
-
-1692,
|
|
79
|
-
-1628,
|
|
80
|
-
-1564,
|
|
81
|
-
-1500,
|
|
82
|
-
-1436,
|
|
83
|
-
-1372,
|
|
84
|
-
-1308,
|
|
85
|
-
-1244,
|
|
86
|
-
-1180,
|
|
87
|
-
-1116,
|
|
88
|
-
-1052,
|
|
89
|
-
-988,
|
|
90
|
-
-924,
|
|
91
|
-
-876,
|
|
92
|
-
-844,
|
|
93
|
-
-812,
|
|
94
|
-
-780,
|
|
95
|
-
-748,
|
|
96
|
-
-716,
|
|
97
|
-
-684,
|
|
98
|
-
-652,
|
|
99
|
-
-620,
|
|
100
|
-
-588,
|
|
101
|
-
-556,
|
|
102
|
-
-524,
|
|
103
|
-
-492,
|
|
104
|
-
-460,
|
|
105
|
-
-428,
|
|
106
|
-
-396,
|
|
107
|
-
-372,
|
|
108
|
-
-356,
|
|
109
|
-
-340,
|
|
110
|
-
-324,
|
|
111
|
-
-308,
|
|
112
|
-
-292,
|
|
113
|
-
-276,
|
|
114
|
-
-260,
|
|
115
|
-
-244,
|
|
116
|
-
-228,
|
|
117
|
-
-212,
|
|
118
|
-
-196,
|
|
119
|
-
-180,
|
|
120
|
-
-164,
|
|
121
|
-
-148,
|
|
122
|
-
-132,
|
|
123
|
-
-120,
|
|
124
|
-
-112,
|
|
125
|
-
-104,
|
|
126
|
-
-96,
|
|
127
|
-
-88,
|
|
128
|
-
-80,
|
|
129
|
-
-72,
|
|
130
|
-
-64,
|
|
131
|
-
-56,
|
|
132
|
-
-48,
|
|
133
|
-
-40,
|
|
134
|
-
-32,
|
|
135
|
-
-24,
|
|
136
|
-
-16,
|
|
137
|
-
-8,
|
|
138
|
-
0,
|
|
139
|
-
32124,
|
|
140
|
-
31100,
|
|
141
|
-
30076,
|
|
142
|
-
29052,
|
|
143
|
-
28028,
|
|
144
|
-
27004,
|
|
145
|
-
25980,
|
|
146
|
-
24956,
|
|
147
|
-
23932,
|
|
148
|
-
22908,
|
|
149
|
-
21884,
|
|
150
|
-
20860,
|
|
151
|
-
19836,
|
|
152
|
-
18812,
|
|
153
|
-
17788,
|
|
154
|
-
16764,
|
|
155
|
-
15996,
|
|
156
|
-
15484,
|
|
157
|
-
14972,
|
|
158
|
-
14460,
|
|
159
|
-
13948,
|
|
160
|
-
13436,
|
|
161
|
-
12924,
|
|
162
|
-
12412,
|
|
163
|
-
11900,
|
|
164
|
-
11388,
|
|
165
|
-
10876,
|
|
166
|
-
10364,
|
|
167
|
-
9852,
|
|
168
|
-
9340,
|
|
169
|
-
8828,
|
|
170
|
-
8316,
|
|
171
|
-
7932,
|
|
172
|
-
7676,
|
|
173
|
-
7420,
|
|
174
|
-
7164,
|
|
175
|
-
6908,
|
|
176
|
-
6652,
|
|
177
|
-
6396,
|
|
178
|
-
6140,
|
|
179
|
-
5884,
|
|
180
|
-
5628,
|
|
181
|
-
5372,
|
|
182
|
-
5116,
|
|
183
|
-
4860,
|
|
184
|
-
4604,
|
|
185
|
-
4348,
|
|
186
|
-
4092,
|
|
187
|
-
3900,
|
|
188
|
-
3772,
|
|
189
|
-
3644,
|
|
190
|
-
3516,
|
|
191
|
-
3388,
|
|
192
|
-
3260,
|
|
193
|
-
3132,
|
|
194
|
-
3004,
|
|
195
|
-
2876,
|
|
196
|
-
2748,
|
|
197
|
-
2620,
|
|
198
|
-
2492,
|
|
199
|
-
2364,
|
|
200
|
-
2236,
|
|
201
|
-
2108,
|
|
202
|
-
1980,
|
|
203
|
-
1884,
|
|
204
|
-
1820,
|
|
205
|
-
1756,
|
|
206
|
-
1692,
|
|
207
|
-
1628,
|
|
208
|
-
1564,
|
|
209
|
-
1500,
|
|
210
|
-
1436,
|
|
211
|
-
1372,
|
|
212
|
-
1308,
|
|
213
|
-
1244,
|
|
214
|
-
1180,
|
|
215
|
-
1116,
|
|
216
|
-
1052,
|
|
217
|
-
988,
|
|
218
|
-
924,
|
|
219
|
-
876,
|
|
220
|
-
844,
|
|
221
|
-
812,
|
|
222
|
-
780,
|
|
223
|
-
748,
|
|
224
|
-
716,
|
|
225
|
-
684,
|
|
226
|
-
652,
|
|
227
|
-
620,
|
|
228
|
-
588,
|
|
229
|
-
556,
|
|
230
|
-
524,
|
|
231
|
-
492,
|
|
232
|
-
460,
|
|
233
|
-
428,
|
|
234
|
-
396,
|
|
235
|
-
372,
|
|
236
|
-
356,
|
|
237
|
-
340,
|
|
238
|
-
324,
|
|
239
|
-
308,
|
|
240
|
-
292,
|
|
241
|
-
276,
|
|
242
|
-
260,
|
|
243
|
-
244,
|
|
244
|
-
228,
|
|
245
|
-
212,
|
|
246
|
-
196,
|
|
247
|
-
180,
|
|
248
|
-
164,
|
|
249
|
-
148,
|
|
250
|
-
132,
|
|
251
|
-
120,
|
|
252
|
-
112,
|
|
253
|
-
104,
|
|
254
|
-
96,
|
|
255
|
-
88,
|
|
256
|
-
80,
|
|
257
|
-
72,
|
|
258
|
-
64,
|
|
259
|
-
56,
|
|
260
|
-
48,
|
|
261
|
-
40,
|
|
262
|
-
32,
|
|
263
|
-
24,
|
|
264
|
-
16,
|
|
265
|
-
8,
|
|
266
|
-
0
|
|
267
|
-
];
|
|
268
|
-
function encodeUlawSample(sample) {
|
|
269
|
-
let sign = 0;
|
|
270
|
-
if (sample < 0) {
|
|
271
|
-
sign = 128;
|
|
272
|
-
sample = -sample;
|
|
273
|
-
}
|
|
274
|
-
if (sample > _CLIP) {
|
|
275
|
-
sample = _CLIP;
|
|
276
|
-
}
|
|
277
|
-
sample += _BIAS;
|
|
278
|
-
let exponent = 7;
|
|
279
|
-
const expValues = [16384, 8192, 4096, 2048, 1024, 512, 256];
|
|
280
|
-
for (const expVal of expValues) {
|
|
281
|
-
if (sample >= expVal) {
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
exponent -= 1;
|
|
285
|
-
}
|
|
286
|
-
const mantissa = sample >> exponent + 3 & 15;
|
|
287
|
-
return ~(sign | exponent << 4 | mantissa) & 255;
|
|
288
|
-
}
|
|
289
|
-
function pcm16ToUlaw(pcm) {
|
|
290
|
-
if (!pcm.length) return Buffer.alloc(0);
|
|
291
|
-
const nSamples = pcm.length >> 1;
|
|
292
|
-
const out = Buffer.alloc(nSamples);
|
|
293
|
-
for (let i = 0; i < nSamples; i++) {
|
|
294
|
-
const sample = pcm.readInt16LE(i * 2);
|
|
295
|
-
out[i] = encodeUlawSample(sample);
|
|
296
|
-
}
|
|
297
|
-
return out;
|
|
298
|
-
}
|
|
299
|
-
function ulawToPcm16(ulaw) {
|
|
300
|
-
if (!ulaw.length) return Buffer.alloc(0);
|
|
301
|
-
const out = Buffer.alloc(ulaw.length * 2);
|
|
302
|
-
for (let i = 0; i < ulaw.length; i++) {
|
|
303
|
-
out.writeInt16LE(DECODE_TABLE[ulaw[i]], i * 2);
|
|
304
|
-
}
|
|
305
|
-
return out;
|
|
306
|
-
}
|
|
307
|
-
function applyPcm16Gain(pcm, gain) {
|
|
308
|
-
if (!pcm.length) return Buffer.alloc(0);
|
|
309
|
-
if (gain === 1) return pcm;
|
|
310
|
-
if (!Number.isFinite(gain) || gain < 0) {
|
|
311
|
-
throw new Error("gain must be a finite number >= 0");
|
|
312
|
-
}
|
|
313
|
-
const nSamples = pcm.length >> 1;
|
|
314
|
-
const out = Buffer.alloc(nSamples * 2);
|
|
315
|
-
for (let i = 0; i < nSamples; i++) {
|
|
316
|
-
let value = Math.round(pcm.readInt16LE(i * 2) * gain);
|
|
317
|
-
if (value > 32767) value = 32767;
|
|
318
|
-
else if (value < -32768) value = -32768;
|
|
319
|
-
out.writeInt16LE(value, i * 2);
|
|
320
|
-
}
|
|
321
|
-
return out;
|
|
322
|
-
}
|
|
323
|
-
function applyUlawGain(ulaw, gain) {
|
|
324
|
-
if (!ulaw.length) return Buffer.alloc(0);
|
|
325
|
-
if (gain === 1) return ulaw;
|
|
326
|
-
return pcm16ToUlaw(applyPcm16Gain(ulawToPcm16(ulaw), gain));
|
|
327
|
-
}
|
|
328
|
-
function resamplePcm16(pcm, fromRate, toRate) {
|
|
329
|
-
if (fromRate === toRate || !pcm.length) return pcm;
|
|
330
|
-
const nSamples = pcm.length >> 1;
|
|
331
|
-
const ratio = fromRate / toRate;
|
|
332
|
-
const outLen = Math.floor(nSamples / ratio);
|
|
333
|
-
const out = Buffer.alloc(outLen * 2);
|
|
334
|
-
for (let i = 0; i < outLen; i++) {
|
|
335
|
-
const srcPos = i * ratio;
|
|
336
|
-
const idx = Math.floor(srcPos);
|
|
337
|
-
const frac = srcPos - idx;
|
|
338
|
-
let val;
|
|
339
|
-
if (idx + 1 < nSamples) {
|
|
340
|
-
val = pcm.readInt16LE(idx * 2) * (1 - frac) + pcm.readInt16LE((idx + 1) * 2) * frac;
|
|
341
|
-
} else {
|
|
342
|
-
val = pcm.readInt16LE(idx * 2);
|
|
343
|
-
}
|
|
344
|
-
out.writeInt16LE(Math.round(val), i * 2);
|
|
345
|
-
}
|
|
346
|
-
return out;
|
|
347
|
-
}
|
|
348
|
-
var DEFAULT_LOGGER = pino({ name: "clawops.agent" });
|
|
349
|
-
var NOOP_LOGGER = pino({ level: "silent" });
|
|
350
|
-
function createAgentLogger(userLogger) {
|
|
351
|
-
return userLogger ?? DEFAULT_LOGGER;
|
|
352
|
-
}
|
|
353
|
-
function createPipelineLogger(parent) {
|
|
354
|
-
return parent.child({ module: "pipeline" });
|
|
355
|
-
}
|
|
356
|
-
|
|
357
8
|
// src/agent/control-ws.ts
|
|
358
9
|
var INITIAL_RECONNECT_DELAY = 1e3;
|
|
359
10
|
var MAX_RECONNECT_DELAY = 3e4;
|
|
@@ -1088,6 +739,7 @@ var CallSession = class {
|
|
|
1088
739
|
startTime;
|
|
1089
740
|
metadata;
|
|
1090
741
|
_status;
|
|
742
|
+
_endedStatus = null;
|
|
1091
743
|
_sendAudioFn = null;
|
|
1092
744
|
_clearAudioFn = null;
|
|
1093
745
|
_hangupFn = null;
|
|
@@ -1097,6 +749,17 @@ var CallSession = class {
|
|
|
1097
749
|
_transferFn = null;
|
|
1098
750
|
/** @internal */
|
|
1099
751
|
_isTransportConnected = null;
|
|
752
|
+
/**
|
|
753
|
+
* @internal Media WS playout 마커 훅. LiveKit(`ClawOpsAudioOutput`)이 재생 완료
|
|
754
|
+
* 판정(mark echo)과 barge-in 절단 위치 계산에 쓴다. 다른 세션 타입은 읽지 않는다.
|
|
755
|
+
* prewarm 중(BufferingCall)에는 바인딩되지 않아 null 이다.
|
|
756
|
+
*/
|
|
757
|
+
/** @internal */
|
|
758
|
+
_sendMark = null;
|
|
759
|
+
/** @internal */
|
|
760
|
+
_waitForMark = null;
|
|
761
|
+
/** @internal */
|
|
762
|
+
_flushTransport = null;
|
|
1100
763
|
_dtmfCollectorActive = false;
|
|
1101
764
|
_dtmfResolvers = [];
|
|
1102
765
|
_dtmfBuffer = [];
|
|
@@ -1125,6 +788,17 @@ var CallSession = class {
|
|
|
1125
788
|
get status() {
|
|
1126
789
|
return this._status;
|
|
1127
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* 서버가 통보한 최종 종료 상태. 통화가 끝나기 전에는 null.
|
|
793
|
+
*
|
|
794
|
+
* `completed`(성사) / `no-answer`(벨은 울렸으나 무응답) / `busy`(통화중) /
|
|
795
|
+
* `rejected`(수신 거절) / `canceled`(응답 전 발신 측 취소) / `failed`(시스템·망 오류).
|
|
796
|
+
* `status` 는 SDK 내부 수명주기(ringing→active→ended)이므로 통화 성사 여부는
|
|
797
|
+
* 이 값이나 `call_failed` 이벤트로 판단한다.
|
|
798
|
+
*/
|
|
799
|
+
get endedStatus() {
|
|
800
|
+
return this._endedStatus;
|
|
801
|
+
}
|
|
1128
802
|
get duration() {
|
|
1129
803
|
return (Date.now() - this.startTime.getTime()) / 1e3;
|
|
1130
804
|
}
|
|
@@ -1285,8 +959,20 @@ var CallSession = class {
|
|
|
1285
959
|
async wait() {
|
|
1286
960
|
return this._endedPromise;
|
|
1287
961
|
}
|
|
1288
|
-
/**
|
|
1289
|
-
|
|
962
|
+
/**
|
|
963
|
+
* Mark the session as ended (called internally).
|
|
964
|
+
*
|
|
965
|
+
* @param status 서버가 통보한 최종 상태(completed/no-answer/busy/rejected/canceled/
|
|
966
|
+
* failed). 주어지면 `endedStatus` 로 확정한다 — 상대가 받지 않은 통화를 성사된 통화와
|
|
967
|
+
* 구분하기 위함이다. 생략하면 미디어 세션 정리 경로에서의 호출이므로, 아직 종료 전일
|
|
968
|
+
* 때만 'completed' 로 채우고 이미 확정된 서버 상태는 덮어쓰지 않는다.
|
|
969
|
+
*/
|
|
970
|
+
_markEnded(status) {
|
|
971
|
+
if (status !== void 0) {
|
|
972
|
+
this._endedStatus = status;
|
|
973
|
+
} else if (this._status !== "ended") {
|
|
974
|
+
this._endedStatus = "completed";
|
|
975
|
+
}
|
|
1290
976
|
this._status = "ended";
|
|
1291
977
|
this._resolveEnded();
|
|
1292
978
|
}
|
|
@@ -1310,35 +996,6 @@ var CallSession = class {
|
|
|
1310
996
|
}
|
|
1311
997
|
}
|
|
1312
998
|
};
|
|
1313
|
-
|
|
1314
|
-
// src/agent/builtin-tool.ts
|
|
1315
|
-
var BuiltinTool = /* @__PURE__ */ ((BuiltinTool2) => {
|
|
1316
|
-
BuiltinTool2["HANG_UP"] = "hang_up";
|
|
1317
|
-
BuiltinTool2["COLLECT_DTMF"] = "collect_dtmf";
|
|
1318
|
-
BuiltinTool2["SEND_DTMF"] = "send_dtmf";
|
|
1319
|
-
BuiltinTool2["TRANSFER_CALL"] = "transfer_call";
|
|
1320
|
-
BuiltinTool2["ALL"] = "all";
|
|
1321
|
-
BuiltinTool2["NONE"] = "none";
|
|
1322
|
-
return BuiltinTool2;
|
|
1323
|
-
})(BuiltinTool || {});
|
|
1324
|
-
var INDIVIDUAL_TOOLS = /* @__PURE__ */ new Set([
|
|
1325
|
-
"hang_up" /* HANG_UP */,
|
|
1326
|
-
"collect_dtmf" /* COLLECT_DTMF */,
|
|
1327
|
-
"send_dtmf" /* SEND_DTMF */,
|
|
1328
|
-
"transfer_call" /* TRANSFER_CALL */
|
|
1329
|
-
]);
|
|
1330
|
-
function resolveBuiltinTools(value) {
|
|
1331
|
-
if (typeof value === "string") {
|
|
1332
|
-
if (value === "all" /* ALL */) {
|
|
1333
|
-
return new Set(INDIVIDUAL_TOOLS);
|
|
1334
|
-
}
|
|
1335
|
-
if (value === "none" /* NONE */) {
|
|
1336
|
-
return /* @__PURE__ */ new Set();
|
|
1337
|
-
}
|
|
1338
|
-
return /* @__PURE__ */ new Set([value]);
|
|
1339
|
-
}
|
|
1340
|
-
return new Set(value.filter((t) => INDIVIDUAL_TOOLS.has(t)));
|
|
1341
|
-
}
|
|
1342
999
|
var CHUNK_SIZE = 160;
|
|
1343
1000
|
var SAMPLE_RATE2 = 8e3;
|
|
1344
1001
|
var BELL_PARTIALS = [
|
|
@@ -1967,10 +1624,15 @@ var ClawOpsAgent = class _ClawOpsAgent {
|
|
|
1967
1624
|
}
|
|
1968
1625
|
_handleEnded(event) {
|
|
1969
1626
|
const callId = event["callId"];
|
|
1627
|
+
const status = event["status"] || "completed";
|
|
1970
1628
|
const session = this._activeSessions.get(callId);
|
|
1971
1629
|
if (session) {
|
|
1972
|
-
this._log.info("Call ended (server): %s", callId);
|
|
1973
|
-
|
|
1630
|
+
this._log.info("Call ended (server): %s (status=%s)", callId, status);
|
|
1631
|
+
if (status !== "completed") {
|
|
1632
|
+
this._log.info("Outbound call not connected: %s (%s)", callId, status);
|
|
1633
|
+
session._emit("call_failed", status);
|
|
1634
|
+
}
|
|
1635
|
+
session._markEnded(status);
|
|
1974
1636
|
this._activeSessions.delete(callId);
|
|
1975
1637
|
}
|
|
1976
1638
|
void this._cleanupPrewarm(callId);
|
|
@@ -2082,9 +1744,10 @@ var ClawOpsAgent = class _ClawOpsAgent {
|
|
|
2082
1744
|
const callId = event["callId"];
|
|
2083
1745
|
const session = this._activeSessions.get(callId);
|
|
2084
1746
|
if (session) {
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
session.
|
|
1747
|
+
const reason = event["reason"] ?? "failed";
|
|
1748
|
+
this._log.info("Outbound call failed: %s (%s)", callId, reason);
|
|
1749
|
+
session._emit("call_failed", reason);
|
|
1750
|
+
session._markEnded(reason);
|
|
2088
1751
|
this._activeSessions.delete(callId);
|
|
2089
1752
|
}
|
|
2090
1753
|
void this._cleanupPrewarm(callId);
|
|
@@ -2199,6 +1862,9 @@ var ClawOpsAgent = class _ClawOpsAgent {
|
|
|
2199
1862
|
() => mediaWs.isConnected
|
|
2200
1863
|
);
|
|
2201
1864
|
session._transferFn = (params) => this._controlWs.requestTransfer(session.callId, params);
|
|
1865
|
+
session._sendMark = (name) => mediaWs.sendMark(name);
|
|
1866
|
+
session._waitForMark = (name, timeoutMs) => mediaWs.waitForMark(name, timeoutMs);
|
|
1867
|
+
session._flushTransport = () => mediaWs.flush();
|
|
2202
1868
|
const sessionHandler = this._session;
|
|
2203
1869
|
if ("setToolRegistry" in sessionHandler && typeof sessionHandler.setToolRegistry === "function") {
|
|
2204
1870
|
sessionHandler.setToolRegistry(sessionTools);
|
|
@@ -2314,232 +1980,6 @@ var ClawOpsAgent = class _ClawOpsAgent {
|
|
|
2314
1980
|
}
|
|
2315
1981
|
};
|
|
2316
1982
|
|
|
2317
|
-
// src/agent/pipeline/builtin-tool-schemas.ts
|
|
2318
|
-
var HANG_UP = {
|
|
2319
|
-
name: "hang_up",
|
|
2320
|
-
description: "End the phone call. Use when the conversation is finished or the caller says goodbye.",
|
|
2321
|
-
parameters: { type: "object", properties: {} }
|
|
2322
|
-
};
|
|
2323
|
-
var COLLECT_DTMF = {
|
|
2324
|
-
name: "collect_dtmf",
|
|
2325
|
-
description: "\uC0AC\uC6A9\uC790\uB85C\uBD80\uD130 DTMF(\uC804\uD654 \uD0A4\uD328\uB4DC) \uC785\uB825\uC744 \uC218\uC9D1\uD569\uB2C8\uB2E4. \uBC18\uB4DC\uC2DC \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB34\uC5C7\uC744 \uC785\uB825\uD574\uC57C \uD558\uB294\uC9C0 \uC548\uB0B4\uD55C \uD6C4 \uD638\uCD9C\uD558\uC138\uC694.",
|
|
2326
|
-
parameters: {
|
|
2327
|
-
type: "object",
|
|
2328
|
-
properties: {
|
|
2329
|
-
max_digits: { type: "integer", description: "\uC218\uC9D1\uD560 \uCD5C\uB300 \uC790\uB9BF\uC218" },
|
|
2330
|
-
finish_on_key: { type: "string", description: "\uC785\uB825 \uC885\uB8CC \uD0A4 (\uAE30\uBCF8: #)" },
|
|
2331
|
-
timeout: { type: "integer", description: "\uC785\uB825 \uB300\uAE30 \uC2DC\uAC04(\uCD08, \uAE30\uBCF8: 5)" }
|
|
2332
|
-
},
|
|
2333
|
-
required: ["max_digits"]
|
|
2334
|
-
}
|
|
2335
|
-
};
|
|
2336
|
-
var SEND_DTMF = {
|
|
2337
|
-
name: "send_dtmf",
|
|
2338
|
-
description: "DTMF \uC2E0\uD638\uB97C \uC804\uC1A1\uD569\uB2C8\uB2E4. ARS \uBA54\uB274 \uD0D0\uC0C9\uC774\uB098 \uB0B4\uC120\uBC88\uD638 \uC785\uB825 \uC2DC \uC0AC\uC6A9\uD569\uB2C8\uB2E4.",
|
|
2339
|
-
parameters: {
|
|
2340
|
-
type: "object",
|
|
2341
|
-
properties: {
|
|
2342
|
-
digits: {
|
|
2343
|
-
type: "string",
|
|
2344
|
-
description: "\uC804\uC1A1\uD560 \uBC88\uD638 (0-9, *, #). 'w'\uB294 500ms \uB300\uAE30, 'W'\uB294 1000ms \uB300\uAE30. \uC608: '1', '1234#', '1w2'"
|
|
2345
|
-
}
|
|
2346
|
-
},
|
|
2347
|
-
required: ["digits"]
|
|
2348
|
-
}
|
|
2349
|
-
};
|
|
2350
|
-
var TRANSFER_CALL = {
|
|
2351
|
-
name: "transfer_call",
|
|
2352
|
-
description: "Transfer the current call to another phone number or SIP endpoint. Use for blind transfer (direct handoff) or warm transfer (with whisper message to the target).",
|
|
2353
|
-
parameters: {
|
|
2354
|
-
type: "object",
|
|
2355
|
-
properties: {
|
|
2356
|
-
to: { type: "string", description: "Transfer destination. A phone number when destination_type is 'pstn', or a SIP URI (e.g. 'sip:user@host') when destination_type is 'sip'." },
|
|
2357
|
-
destination_type: { type: "string", enum: ["pstn", "sip"], description: "pstn: dial a phone number via carrier (default). sip: connect directly to a SIP endpoint (no carrier/PSTN)." },
|
|
2358
|
-
mode: { type: "string", enum: ["blind", "warm"], description: "blind: direct transfer (default), warm: play whisper to target first" },
|
|
2359
|
-
after_transfer: { type: "string", enum: ["terminate", "return"], description: "terminate: end AI session (default), return: AI resumes after transfer ends" },
|
|
2360
|
-
whisper: { type: "string", description: "Message to speak to transfer target before connecting customer (warm mode only)" },
|
|
2361
|
-
caller_id: { type: "string", description: "Override caller ID for the transfer leg" },
|
|
2362
|
-
timeout: { type: "integer", description: "Seconds to wait for transfer target to answer (default 30)" }
|
|
2363
|
-
},
|
|
2364
|
-
required: ["to"]
|
|
2365
|
-
}
|
|
2366
|
-
};
|
|
2367
|
-
var TOOL_MAP = /* @__PURE__ */ new Map([
|
|
2368
|
-
["hang_up" /* HANG_UP */, HANG_UP],
|
|
2369
|
-
["collect_dtmf" /* COLLECT_DTMF */, COLLECT_DTMF],
|
|
2370
|
-
["send_dtmf" /* SEND_DTMF */, SEND_DTMF],
|
|
2371
|
-
["transfer_call" /* TRANSFER_CALL */, TRANSFER_CALL]
|
|
2372
|
-
]);
|
|
2373
|
-
var BUILTIN_TOOL_NAMES = new Set(
|
|
2374
|
-
Array.from(TOOL_MAP.values()).map((s) => s.name)
|
|
2375
|
-
);
|
|
2376
|
-
function toChatCompletions(schema) {
|
|
2377
|
-
return {
|
|
2378
|
-
type: "function",
|
|
2379
|
-
function: {
|
|
2380
|
-
name: schema.name,
|
|
2381
|
-
description: schema.description,
|
|
2382
|
-
parameters: schema.parameters
|
|
2383
|
-
}
|
|
2384
|
-
};
|
|
2385
|
-
}
|
|
2386
|
-
function toRealtime(schema) {
|
|
2387
|
-
return {
|
|
2388
|
-
type: "function",
|
|
2389
|
-
name: schema.name,
|
|
2390
|
-
description: schema.description,
|
|
2391
|
-
parameters: schema.parameters
|
|
2392
|
-
};
|
|
2393
|
-
}
|
|
2394
|
-
function toGemini(schema) {
|
|
2395
|
-
return {
|
|
2396
|
-
name: schema.name,
|
|
2397
|
-
description: schema.description,
|
|
2398
|
-
parameters: schema.parameters
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
var CONVERTERS = {
|
|
2402
|
-
chat: toChatCompletions,
|
|
2403
|
-
realtime: toRealtime,
|
|
2404
|
-
gemini: toGemini
|
|
2405
|
-
};
|
|
2406
|
-
function getBuiltinToolSchemas(builtinTools, fmt) {
|
|
2407
|
-
const converter = CONVERTERS[fmt];
|
|
2408
|
-
const result = [];
|
|
2409
|
-
for (const [toolEnum, schema] of TOOL_MAP) {
|
|
2410
|
-
if (builtinTools === null || builtinTools.has(toolEnum)) {
|
|
2411
|
-
result.push(converter(schema));
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
return result;
|
|
2415
|
-
}
|
|
2416
|
-
function isBuiltinTool(name) {
|
|
2417
|
-
return BUILTIN_TOOL_NAMES.has(name);
|
|
2418
|
-
}
|
|
2419
|
-
async function executeBuiltinTool(funcName, args, call) {
|
|
2420
|
-
if (funcName === "hang_up") {
|
|
2421
|
-
await call.hangup();
|
|
2422
|
-
return "";
|
|
2423
|
-
}
|
|
2424
|
-
if (funcName === "collect_dtmf") {
|
|
2425
|
-
try {
|
|
2426
|
-
const result = await call.collectDtmf({
|
|
2427
|
-
maxDigits: args["max_digits"] ?? 4,
|
|
2428
|
-
finishOnKey: args["finish_on_key"] ?? "#",
|
|
2429
|
-
timeout: args["timeout"] ?? 5
|
|
2430
|
-
});
|
|
2431
|
-
return result || "(\uD0C0\uC784\uC544\uC6C3 - \uC785\uB825 \uC5C6\uC74C)";
|
|
2432
|
-
} catch (e) {
|
|
2433
|
-
return `Error: ${e}`;
|
|
2434
|
-
}
|
|
2435
|
-
}
|
|
2436
|
-
if (funcName === "send_dtmf") {
|
|
2437
|
-
try {
|
|
2438
|
-
await call.sendDtmfSequence(args["digits"] ?? "");
|
|
2439
|
-
return "sent";
|
|
2440
|
-
} catch (e) {
|
|
2441
|
-
return `Error: ${e}`;
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
if (funcName === "transfer_call") {
|
|
2445
|
-
try {
|
|
2446
|
-
call.transfer(args["to"], {
|
|
2447
|
-
destinationType: args["destination_type"] ?? void 0,
|
|
2448
|
-
mode: args["mode"] ?? void 0,
|
|
2449
|
-
afterTransfer: args["after_transfer"] ?? void 0,
|
|
2450
|
-
whisper: args["whisper"] ?? void 0,
|
|
2451
|
-
callerId: args["caller_id"] ?? void 0,
|
|
2452
|
-
timeout: args["timeout"] ?? void 0
|
|
2453
|
-
}).catch(() => {
|
|
2454
|
-
});
|
|
2455
|
-
return JSON.stringify({ status: "transfer_initiated" });
|
|
2456
|
-
} catch (e) {
|
|
2457
|
-
return `Error: ${e}`;
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
return null;
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
// src/agent/pipeline/buffering-call.ts
|
|
2464
|
-
var MetricsStub = class {
|
|
2465
|
-
recordToolCall() {
|
|
2466
|
-
}
|
|
2467
|
-
recordInterrupt() {
|
|
2468
|
-
}
|
|
2469
|
-
recordToolError() {
|
|
2470
|
-
}
|
|
2471
|
-
};
|
|
2472
|
-
var BufferingCall = class {
|
|
2473
|
-
_buffer = [];
|
|
2474
|
-
_droppedEvents = {};
|
|
2475
|
-
metrics = new MetricsStub();
|
|
2476
|
-
async sendAudio(chunk) {
|
|
2477
|
-
this._buffer.push(chunk);
|
|
2478
|
-
}
|
|
2479
|
-
/** clearAudio 도 prewarm 동안엔 no-op (드물긴 하지만 안전하게). */
|
|
2480
|
-
clearAudio() {
|
|
2481
|
-
this._buffer = [];
|
|
2482
|
-
}
|
|
2483
|
-
/**
|
|
2484
|
-
* transcript 등 lifecycle 이벤트는 prewarm 동안 무시한다. silent drop 은 디버깅이
|
|
2485
|
-
* 어려우므로 event name 별 카운터로 누적하고 attachBuffered() 시 한 번에 로깅한다.
|
|
2486
|
-
*/
|
|
2487
|
-
_emit(...args) {
|
|
2488
|
-
this._recordDropped(args);
|
|
2489
|
-
}
|
|
2490
|
-
async emit(...args) {
|
|
2491
|
-
this._recordDropped(args);
|
|
2492
|
-
}
|
|
2493
|
-
_recordDropped(args) {
|
|
2494
|
-
let eventName = "?";
|
|
2495
|
-
if (args.length > 0 && typeof args[0] === "string") {
|
|
2496
|
-
eventName = args[0];
|
|
2497
|
-
}
|
|
2498
|
-
this._droppedEvents[eventName] = (this._droppedEvents[eventName] ?? 0) + 1;
|
|
2499
|
-
}
|
|
2500
|
-
recordToolCall() {
|
|
2501
|
-
}
|
|
2502
|
-
recordToolError() {
|
|
2503
|
-
}
|
|
2504
|
-
recordFirstResponse() {
|
|
2505
|
-
}
|
|
2506
|
-
recordBargeIn() {
|
|
2507
|
-
}
|
|
2508
|
-
drainBuffer() {
|
|
2509
|
-
const out = this._buffer;
|
|
2510
|
-
this._buffer = [];
|
|
2511
|
-
return out;
|
|
2512
|
-
}
|
|
2513
|
-
drainDroppedEvents() {
|
|
2514
|
-
const out = this._droppedEvents;
|
|
2515
|
-
this._droppedEvents = {};
|
|
2516
|
-
return out;
|
|
2517
|
-
}
|
|
2518
|
-
};
|
|
2519
|
-
function attachBuffered(prev, next) {
|
|
2520
|
-
if (!(prev instanceof BufferingCall)) {
|
|
2521
|
-
return false;
|
|
2522
|
-
}
|
|
2523
|
-
const drained = prev.drainBuffer();
|
|
2524
|
-
const flushed = drained.length > 0;
|
|
2525
|
-
const callId = next.callId ?? "?";
|
|
2526
|
-
if (flushed) {
|
|
2527
|
-
console.info(
|
|
2528
|
-
`[PREWARM-T] first-audio call_id=${callId} t=${(process.hrtime.bigint() / 1000000n).toString()} buffered_chunks=${drained.length} source=prebuffer`
|
|
2529
|
-
);
|
|
2530
|
-
}
|
|
2531
|
-
for (const chunk of drained) {
|
|
2532
|
-
next.sendAudio(chunk);
|
|
2533
|
-
}
|
|
2534
|
-
const dropped = prev.drainDroppedEvents();
|
|
2535
|
-
if (Object.keys(dropped).length > 0) {
|
|
2536
|
-
console.info(
|
|
2537
|
-
`[PREWARM] dropped events during prewarm call_id=${callId} events=${JSON.stringify(dropped)}`
|
|
2538
|
-
);
|
|
2539
|
-
}
|
|
2540
|
-
return flushed;
|
|
2541
|
-
}
|
|
2542
|
-
|
|
2543
1983
|
// src/agent/pipeline/pipeline-session.ts
|
|
2544
1984
|
var PipelineSession = class {
|
|
2545
1985
|
_stt;
|
|
@@ -4542,6 +3982,6 @@ function mcpServerHTTP(options) {
|
|
|
4542
3982
|
};
|
|
4543
3983
|
}
|
|
4544
3984
|
|
|
4545
|
-
export { AnthropicLLM, AudioRecorder,
|
|
3985
|
+
export { AnthropicLLM, AudioRecorder, CallSession, ClawOpsAgent, ControlWebSocket, DeepSeekLLM, DeepgramSTT, ElevenLabsTTS, FireworksLLM, GeminiLLM, GeminiRealtime, GroqLLM, MCPClient, MediaWebSocket, MistralLLM, OllamaLLM, OpenAICompatLLM, OpenAILLM, OpenAIRealtime, PerplexityLLM, PipelineSession, TogetherLLM, ToolRegistry, XaiLLM, buildControlWsUrl, functionTool, getTracingConfig, mcpServerHTTP, mcpServerStdio, resetTracingConfig, setTracingConfig, zodToToolParams };
|
|
4546
3986
|
//# sourceMappingURL=index.js.map
|
|
4547
3987
|
//# sourceMappingURL=index.js.map
|