@teamlearners/clawops 0.30.0 → 0.32.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.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkIGFGK3XZ_cjs = require('../chunk-IGFGK3XZ.cjs');
4
- var chunkXAOA3XFQ_cjs = require('../chunk-XAOA3XFQ.cjs');
3
+ var chunkHKXRJRAW_cjs = require('../chunk-HKXRJRAW.cjs');
4
+ var chunkQD2ZY4UP_cjs = require('../chunk-QD2ZY4UP.cjs');
5
5
  var fs = require('fs');
6
6
  var path = require('path');
7
7
  var os = require('os');
@@ -59,7 +59,7 @@ var ControlWebSocket = class {
59
59
  _closed = false;
60
60
  _connectedResolve = null;
61
61
  _connectedPromise;
62
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
62
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
63
63
  _pingTimer = null;
64
64
  setLogger(logger) {
65
65
  this._log = logger;
@@ -224,7 +224,7 @@ var ControlWebSocket = class {
224
224
  var MCPClient = class {
225
225
  _servers = /* @__PURE__ */ new Map();
226
226
  _clients = /* @__PURE__ */ new Map();
227
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
227
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
228
228
  setLogger(logger) {
229
229
  this._log = logger;
230
230
  }
@@ -366,7 +366,7 @@ var MediaWebSocket = class {
366
366
  _onClose = null;
367
367
  _onDtmf = null;
368
368
  _markWaiters = /* @__PURE__ */ new Map();
369
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
369
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
370
370
  setLogger(logger) {
371
371
  this._log = logger;
372
372
  }
@@ -592,7 +592,7 @@ var AudioRecorder = class {
592
592
  _started = false;
593
593
  _baseTs = null;
594
594
  _outCursor = 0;
595
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
595
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
596
596
  setLogger(logger) {
597
597
  this._log = logger;
598
598
  }
@@ -728,7 +728,7 @@ var MAX_ERROR_MESSAGE_LENGTH = 200;
728
728
  function getSdkInfo() {
729
729
  return {
730
730
  name: "clawops-node",
731
- version: chunkIGFGK3XZ_cjs.VERSION,
731
+ version: chunkHKXRJRAW_cjs.VERSION,
732
732
  runtime: `node/${process.versions.node}`,
733
733
  os: `${process.platform}/${os__default.default.arch()}`
734
734
  };
@@ -765,6 +765,7 @@ var CallSession = class {
765
765
  metadata;
766
766
  _status;
767
767
  _endedStatus = null;
768
+ _endedDuration = null;
768
769
  _sendAudioFn = null;
769
770
  _clearAudioFn = null;
770
771
  _hangupFn = null;
@@ -788,7 +789,7 @@ var CallSession = class {
788
789
  _dtmfCollectorActive = false;
789
790
  _dtmfResolvers = [];
790
791
  _dtmfBuffer = [];
791
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
792
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
792
793
  _handlers = /* @__PURE__ */ new Map();
793
794
  _endedPromise;
794
795
  _resolveEnded;
@@ -824,9 +825,22 @@ var CallSession = class {
824
825
  get endedStatus() {
825
826
  return this._endedStatus;
826
827
  }
828
+ /**
829
+ * 서버가 확정한 통화 시간(초). 통화가 끝나기 전에는 `null`.
830
+ *
831
+ * ⚠️ `duration` 과 다르다 — 그쪽은 SDK 가 로컬 시계로 재는 **경과 시간**이라 통화 중에도
832
+ * 읽히고, 세션이 붙기 전후의 오차를 포함한다. 기록·정산에 쓸 값은 이쪽이다.
833
+ */
834
+ get endedDuration() {
835
+ return this._endedDuration;
836
+ }
827
837
  get duration() {
828
838
  return (Date.now() - this.startTime.getTime()) / 1e3;
829
839
  }
840
+ /** @internal 서버가 통보한 통화 시간을 확정한다. */
841
+ _setEndedDuration(seconds) {
842
+ this._endedDuration = seconds;
843
+ }
830
844
  get metrics() {
831
845
  return this._metrics;
832
846
  }
@@ -954,11 +968,27 @@ var CallSession = class {
954
968
  * directly to a SIP endpoint without going through the PSTN carrier. Requires the
955
969
  * account to have an active `sip_trunk` add-on; otherwise the transfer fails and
956
970
  * the call continues with the AI (result `{ status: 'failed', ... }`).
971
+ *
972
+ * 전환받는 쪽에 표시되는 발신번호는 기본이 **계정 보유번호**(인바운드면 착신 070)다.
973
+ *
974
+ * `callerIdMode: 'original'` 은 인바운드 통화의 **원 발신자 번호를 승계하려는 선호**다.
975
+ * 승계할 수 없는 통화(KCT 직결 인입이 아니거나 국내 번호로 정규화되지 않는 발신번호)면
976
+ * 조용히 계정 보유번호로 내려앉고 **전환은 그대로 성사된다**.
977
+ *
978
+ * `callerId` 는 번호를 직접 주는 **지시**라 성격이 다르다. 허용 범위(계정 보유번호 또는
979
+ * KCT 직결 인입의 원 발신자)를 벗어나면 전환 자체가 실패한다. 둘 다 주면 `callerId` 가
980
+ * 이기고 `callerIdMode` 는 무시된다 — 우선순위 판단은 서버가 한다.
957
981
  */
958
982
  async transfer(to, options) {
959
983
  if (!this._transferFn) {
960
984
  throw new Error("transfer not available");
961
985
  }
986
+ const callerIdMode = options?.callerIdMode;
987
+ if (callerIdMode !== void 0 && callerIdMode !== "account" && callerIdMode !== "original") {
988
+ throw new Error(
989
+ `callerIdMode must be 'account' or 'original', got ${JSON.stringify(callerIdMode)}`
990
+ );
991
+ }
962
992
  return this._transferFn({
963
993
  to,
964
994
  destinationType: options?.destinationType ?? "pstn",
@@ -968,7 +998,9 @@ var CallSession = class {
968
998
  whisper: options?.whisper ?? null,
969
999
  context: options?.context ?? null,
970
1000
  callerId: options?.callerId ?? null,
971
- timeout: options?.timeout ?? 30
1001
+ timeout: options?.timeout ?? 30,
1002
+ // 안 주면 키를 붙이지 않는다 — 구 서버와 기존 동작을 그대로 둔다(additive).
1003
+ ...callerIdMode !== void 0 ? { callerIdMode } : {}
972
1004
  });
973
1005
  }
974
1006
  /** Register an event handler. */
@@ -1105,7 +1137,7 @@ function generateComfortTone(volume = 0.12) {
1105
1137
  }
1106
1138
  }
1107
1139
  const pcm = int16ArrayToBuffer(concatInt16Arrays(...parts));
1108
- const ulaw = chunkXAOA3XFQ_cjs.pcm16ToUlaw(pcm);
1140
+ const ulaw = chunkQD2ZY4UP_cjs.pcm16ToUlaw(pcm);
1109
1141
  const chunks = [];
1110
1142
  for (let i = 0; i < ulaw.length; i += CHUNK_SIZE) {
1111
1143
  chunks.push(ulaw.subarray(i, i + CHUNK_SIZE));
@@ -1162,9 +1194,9 @@ function loadHoldAudio(source) {
1162
1194
  pcmData = mono;
1163
1195
  }
1164
1196
  if (sampleRate !== SAMPLE_RATE2) {
1165
- pcmData = chunkXAOA3XFQ_cjs.resamplePcm16(pcmData, sampleRate, SAMPLE_RATE2);
1197
+ pcmData = chunkQD2ZY4UP_cjs.resamplePcm16(pcmData, sampleRate, SAMPLE_RATE2);
1166
1198
  }
1167
- const ulaw = chunkXAOA3XFQ_cjs.pcm16ToUlaw(pcmData);
1199
+ const ulaw = chunkQD2ZY4UP_cjs.pcm16ToUlaw(pcmData);
1168
1200
  const chunks = [];
1169
1201
  for (let i = 0; i < ulaw.length; i += CHUNK_SIZE) {
1170
1202
  chunks.push(ulaw.subarray(i, i + CHUNK_SIZE));
@@ -1398,6 +1430,7 @@ var ATTR_CALL_DIRECTION = "clawops.call.direction";
1398
1430
  var ATTR_AGENT_ID = "clawops.agent.id";
1399
1431
 
1400
1432
  // src/agent/agent.ts
1433
+ var TERMINAL_FRAME_GRACE_MS = 2e3;
1401
1434
  var ClawOpsAgent = class _ClawOpsAgent {
1402
1435
  _apiKey;
1403
1436
  _accountId;
@@ -1411,6 +1444,8 @@ var ClawOpsAgent = class _ClawOpsAgent {
1411
1444
  _recording;
1412
1445
  _recordingPath;
1413
1446
  _activeSessions = /* @__PURE__ */ new Map();
1447
+ /** 미디어 정리를 마친 통화가 서버 종료 프레임을 기다리는 자리. callId → resolve. */
1448
+ _terminalWaiters = /* @__PURE__ */ new Map();
1414
1449
  _builtinTools;
1415
1450
  _passiveDtmfDebounceMs;
1416
1451
  _passiveDtmfBuffer = [];
@@ -1433,13 +1468,13 @@ var ClawOpsAgent = class _ClawOpsAgent {
1433
1468
  constructor(options) {
1434
1469
  this._apiKey = options.apiKey ?? process.env["CLAWOPS_API_KEY"] ?? "";
1435
1470
  this._accountId = options.accountId ?? process.env["CLAWOPS_ACCOUNT_ID"] ?? "";
1436
- this._baseUrl = options.baseUrl ?? chunkIGFGK3XZ_cjs.DEFAULT_BASE_URL;
1471
+ this._baseUrl = options.baseUrl ?? chunkHKXRJRAW_cjs.DEFAULT_BASE_URL;
1437
1472
  this._fromNumber = options.from;
1438
1473
  this._session = options.session;
1439
1474
  this._recording = options.recording ?? false;
1440
1475
  this._recordingPath = options.recordingPath ?? "./recordings";
1441
1476
  this._mcpServers = options.mcpServers ?? [];
1442
- this._builtinTools = chunkXAOA3XFQ_cjs.resolveBuiltinTools(options.builtinTools ?? "all" /* ALL */);
1477
+ this._builtinTools = chunkQD2ZY4UP_cjs.resolveBuiltinTools(options.builtinTools ?? "all" /* ALL */);
1443
1478
  this._passiveDtmfDebounceMs = options.passiveDtmfDebounceMs ?? 500;
1444
1479
  this._rxGain = _ClawOpsAgent._validateGain("rxGain", options.rxGain ?? 1);
1445
1480
  this._txGain = _ClawOpsAgent._validateGain("txGain", options.txGain ?? 1);
@@ -1448,8 +1483,8 @@ var ClawOpsAgent = class _ClawOpsAgent {
1448
1483
  if (options.tracing) {
1449
1484
  setTracingConfig(options.tracing);
1450
1485
  }
1451
- this._log = chunkXAOA3XFQ_cjs.createAgentLogger(options.logger);
1452
- this._pipelineLog = chunkXAOA3XFQ_cjs.createPipelineLogger(this._log);
1486
+ this._log = chunkQD2ZY4UP_cjs.createAgentLogger(options.logger);
1487
+ this._pipelineLog = chunkQD2ZY4UP_cjs.createPipelineLogger(this._log);
1453
1488
  this._isPipelineSession = "_stt" in this._session && "_llm" in this._session;
1454
1489
  if (options.toolConfig?.holdAudio) {
1455
1490
  this._holdAudioChunks = loadHoldAudio(options.toolConfig.holdAudio);
@@ -1457,7 +1492,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1457
1492
  }
1458
1493
  static _validateGain(name, gain) {
1459
1494
  if (typeof gain !== "number" || !Number.isFinite(gain) || gain < 0) {
1460
- throw new chunkIGFGK3XZ_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1495
+ throw new chunkHKXRJRAW_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1461
1496
  }
1462
1497
  return gain;
1463
1498
  }
@@ -1471,7 +1506,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1471
1506
  tool(nameOrTool, description, parameters, handler) {
1472
1507
  if (typeof nameOrTool === "string") {
1473
1508
  if (!description || !parameters || !handler) {
1474
- throw new chunkIGFGK3XZ_cjs.AgentError(
1509
+ throw new chunkHKXRJRAW_cjs.AgentError(
1475
1510
  "tool(name, description, parameters, handler) requires all arguments."
1476
1511
  );
1477
1512
  }
@@ -1507,10 +1542,10 @@ var ClawOpsAgent = class _ClawOpsAgent {
1507
1542
  async connect() {
1508
1543
  if (this._controlWs) return;
1509
1544
  if (!this._apiKey) {
1510
- throw new chunkIGFGK3XZ_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1545
+ throw new chunkHKXRJRAW_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1511
1546
  }
1512
1547
  if (!this._accountId) {
1513
- throw new chunkIGFGK3XZ_cjs.AgentError(
1548
+ throw new chunkHKXRJRAW_cjs.AgentError(
1514
1549
  "Account ID is required. Set CLAWOPS_ACCOUNT_ID or pass accountId option."
1515
1550
  );
1516
1551
  }
@@ -1534,7 +1569,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1534
1569
  } catch {
1535
1570
  }
1536
1571
  } catch (err) {
1537
- throw new chunkIGFGK3XZ_cjs.AgentConnectionError(
1572
+ throw new chunkHKXRJRAW_cjs.AgentConnectionError(
1538
1573
  `Failed to connect to ClawOps: ${err instanceof Error ? err.message : String(err)}`
1539
1574
  );
1540
1575
  }
@@ -1560,6 +1595,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1560
1595
  this._controlWs.close();
1561
1596
  this._controlWs = null;
1562
1597
  }
1598
+ for (const wake of [...this._terminalWaiters.values()]) wake();
1563
1599
  for (const session of this._activeSessions.values()) {
1564
1600
  session._markEnded();
1565
1601
  }
@@ -1598,7 +1634,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1598
1634
  });
1599
1635
  if (resp.status !== 201) {
1600
1636
  const error = await resp.json();
1601
- throw new chunkIGFGK3XZ_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1637
+ throw new chunkHKXRJRAW_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1602
1638
  }
1603
1639
  const data = await resp.json();
1604
1640
  const callSession = new CallSession({
@@ -1647,12 +1683,43 @@ var ClawOpsAgent = class _ClawOpsAgent {
1647
1683
  this._safeStartCallSession(session, mediaUrl, callId);
1648
1684
  }
1649
1685
  }
1686
+ /**
1687
+ * 서버 종료 프레임을 짧게 기다린다. 미디어 정리 직후에만 부른다.
1688
+ *
1689
+ * 왜 기다리나: `call_end` 는 인바운드 사용자가 통화 결과를 받는 **유일한 통로**인데, 서버는
1690
+ * 미디어 WS 를 먼저 닫고 자원 정리를 마친 뒤에야 control 종료 프레임을 보낸다. 안 기다리면
1691
+ * 그 핸들러 안에서 `endedDuration` 은 영영 null 이다.
1692
+ *
1693
+ * 상한을 다 쓰는 경우는 제어 연결이 죽어 프레임이 아예 안 오는 때뿐이다 — 그 프레임은
1694
+ * 예전부터 늘 오던 것이고(이번에 바뀐 건 내용뿐), 정상 경로에서는 밀리초 안에 풀린다.
1695
+ */
1696
+ async _awaitServerTerminal(session) {
1697
+ if (session.endedDuration !== null) return;
1698
+ await new Promise((resolve) => {
1699
+ const done = () => {
1700
+ clearTimeout(timer);
1701
+ this._terminalWaiters.delete(session.callId);
1702
+ resolve();
1703
+ };
1704
+ const timer = setTimeout(() => {
1705
+ this._log.debug(
1706
+ "\uC11C\uBC84 \uC885\uB8CC \uD504\uB808\uC784\uC774 %dms \uC548\uC5D0 \uC624\uC9C0 \uC54A\uC558\uB2E4 \u2014 endedDuration \uC5C6\uC774 \uC9C4\uD589: %s",
1707
+ TERMINAL_FRAME_GRACE_MS,
1708
+ session.callId
1709
+ );
1710
+ done();
1711
+ }, TERMINAL_FRAME_GRACE_MS);
1712
+ this._terminalWaiters.set(session.callId, done);
1713
+ });
1714
+ }
1650
1715
  _handleEnded(event) {
1651
1716
  const callId = event["callId"];
1652
1717
  const status = event["status"] || "completed";
1718
+ const endedDuration = event["duration"];
1653
1719
  const session = this._activeSessions.get(callId);
1654
1720
  if (session) {
1655
1721
  this._log.info("Call ended (server): %s (status=%s)", callId, status);
1722
+ if (typeof endedDuration === "number") session._setEndedDuration(endedDuration);
1656
1723
  if (status !== "completed") {
1657
1724
  this._log.info("Outbound call not connected: %s (%s)", callId, status);
1658
1725
  session._emit("call_failed", status);
@@ -1660,6 +1727,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1660
1727
  session._markEnded(status);
1661
1728
  this._activeSessions.delete(callId);
1662
1729
  }
1730
+ this._terminalWaiters.get(callId)?.();
1663
1731
  void this._cleanupPrewarm(callId);
1664
1732
  }
1665
1733
  /**
@@ -1896,9 +1964,9 @@ var ClawOpsAgent = class _ClawOpsAgent {
1896
1964
  let latestMediaTs = 0;
1897
1965
  session._bindTransport(
1898
1966
  (audio) => {
1899
- const gained = chunkXAOA3XFQ_cjs.applyUlawGain(audio, this._txGain);
1967
+ const gained = chunkQD2ZY4UP_cjs.applyUlawGain(audio, this._txGain);
1900
1968
  if (recorder) {
1901
- recorder.writeOutbound(chunkXAOA3XFQ_cjs.ulawToPcm16(gained), latestMediaTs);
1969
+ recorder.writeOutbound(chunkQD2ZY4UP_cjs.ulawToPcm16(gained), latestMediaTs);
1902
1970
  }
1903
1971
  mediaWs.sendAudio(gained.toString("base64"));
1904
1972
  session.recordFirstResponse();
@@ -1928,9 +1996,9 @@ var ClawOpsAgent = class _ClawOpsAgent {
1928
1996
  this._callSessions.set(session.callId, sessionHandler);
1929
1997
  mediaWs.onAudio((ulawAudio, timestamp) => {
1930
1998
  latestMediaTs = timestamp;
1931
- const gained = chunkXAOA3XFQ_cjs.applyUlawGain(ulawAudio, this._rxGain);
1999
+ const gained = chunkQD2ZY4UP_cjs.applyUlawGain(ulawAudio, this._rxGain);
1932
2000
  if (recorder) {
1933
- recorder.writeInbound(chunkXAOA3XFQ_cjs.ulawToPcm16(gained), timestamp);
2001
+ recorder.writeInbound(chunkQD2ZY4UP_cjs.ulawToPcm16(gained), timestamp);
1934
2002
  }
1935
2003
  if (sessionHandler) {
1936
2004
  sessionHandler.feedAudio(gained, timestamp);
@@ -2014,6 +2082,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
2014
2082
  this._controlWs?.send({ event: "call.metrics", callId: session.callId, metrics: session.metrics });
2015
2083
  } catch {
2016
2084
  }
2085
+ await this._awaitServerTerminal(session);
2017
2086
  session._emit("call_end");
2018
2087
  session._markEnded();
2019
2088
  this._activeSessions.delete(session.callId);
@@ -2045,7 +2114,7 @@ var PipelineSession = class {
2045
2114
  _speaking = false;
2046
2115
  _builtinTools = null;
2047
2116
  _holdAudioChunks = null;
2048
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
2117
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
2049
2118
  constructor(options) {
2050
2119
  this._stt = options.stt;
2051
2120
  this._llm = options.llm;
@@ -2107,7 +2176,7 @@ var PipelineSession = class {
2107
2176
  */
2108
2177
  async prewarm(tools) {
2109
2178
  if (tools) this._tools = tools;
2110
- this._callSession = new chunkXAOA3XFQ_cjs.BufferingCall();
2179
+ this._callSession = new chunkQD2ZY4UP_cjs.BufferingCall();
2111
2180
  this._running = true;
2112
2181
  this._conversation = [];
2113
2182
  this._log.info("PipelineSession prewarmed");
@@ -2130,7 +2199,7 @@ var PipelineSession = class {
2130
2199
  async attach(callSession) {
2131
2200
  const prev = this._callSession;
2132
2201
  this._callSession = callSession;
2133
- chunkXAOA3XFQ_cjs.attachBuffered(prev, callSession);
2202
+ chunkQD2ZY4UP_cjs.attachBuffered(prev, callSession);
2134
2203
  }
2135
2204
  async start(callSession, tools) {
2136
2205
  this._tools = tools ?? null;
@@ -2177,8 +2246,8 @@ var PipelineSession = class {
2177
2246
  while (this._running) {
2178
2247
  if (this._audioBuffer.length > 0) {
2179
2248
  const ulaw = this._audioBuffer.shift();
2180
- const pcm8k = chunkXAOA3XFQ_cjs.ulawToPcm16(ulaw);
2181
- const pcm16k = chunkXAOA3XFQ_cjs.resamplePcm16(pcm8k, 8e3, 16e3);
2249
+ const pcm8k = chunkQD2ZY4UP_cjs.ulawToPcm16(ulaw);
2250
+ const pcm16k = chunkQD2ZY4UP_cjs.resamplePcm16(pcm8k, 8e3, 16e3);
2182
2251
  yield pcm16k;
2183
2252
  } else {
2184
2253
  await new Promise((resolve) => setTimeout(resolve, 20));
@@ -2194,7 +2263,7 @@ var PipelineSession = class {
2194
2263
  await this._respond();
2195
2264
  }
2196
2265
  _buildEffectiveTools() {
2197
- const builtinSchemas = chunkXAOA3XFQ_cjs.getBuiltinToolSchemas(this._builtinTools, "chat");
2266
+ const builtinSchemas = chunkQD2ZY4UP_cjs.getBuiltinToolSchemas(this._builtinTools, "chat");
2198
2267
  const dtmfSchemas = builtinSchemas.filter((s) => {
2199
2268
  const name = s["function"]?.["name"];
2200
2269
  return name === "collect_dtmf" || name === "send_dtmf";
@@ -2243,8 +2312,8 @@ var PipelineSession = class {
2243
2312
  const { id, name, arguments: argsStr } = chunk.toolCall;
2244
2313
  try {
2245
2314
  const args = JSON.parse(argsStr);
2246
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(name) && this._callSession && !(this._callSession instanceof chunkXAOA3XFQ_cjs.BufferingCall)) {
2247
- const result2 = await chunkXAOA3XFQ_cjs.executeBuiltinTool(name, args, this._callSession);
2315
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(name) && this._callSession && !(this._callSession instanceof chunkQD2ZY4UP_cjs.BufferingCall)) {
2316
+ const result2 = await chunkQD2ZY4UP_cjs.executeBuiltinTool(name, args, this._callSession);
2248
2317
  if (result2 !== null) {
2249
2318
  if (name === "hang_up") return;
2250
2319
  this._conversation.push({ role: "tool", content: result2, tool_call_id: id, name });
@@ -2252,11 +2321,11 @@ var PipelineSession = class {
2252
2321
  return;
2253
2322
  }
2254
2323
  }
2255
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(name) && this._callSession instanceof chunkXAOA3XFQ_cjs.BufferingCall) {
2324
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(name) && this._callSession instanceof chunkQD2ZY4UP_cjs.BufferingCall) {
2256
2325
  this._log.warn("Builtin tool %s called before answer \u2014 deferring", name);
2257
2326
  this._conversation.push({
2258
2327
  role: "tool",
2259
- content: chunkXAOA3XFQ_cjs.CALL_NOT_READY_RESULT,
2328
+ content: chunkQD2ZY4UP_cjs.CALL_NOT_READY_RESULT,
2260
2329
  tool_call_id: id,
2261
2330
  name
2262
2331
  });
@@ -2265,7 +2334,7 @@ var PipelineSession = class {
2265
2334
  }
2266
2335
  if (!this._tools) return;
2267
2336
  this._callSession?.recordToolCall();
2268
- const player = this._holdAudioChunks && this._callSession && !(this._callSession instanceof chunkXAOA3XFQ_cjs.BufferingCall) ? new HoldAudioPlayer(this._callSession, this._holdAudioChunks) : null;
2337
+ const player = this._holdAudioChunks && this._callSession && !(this._callSession instanceof chunkQD2ZY4UP_cjs.BufferingCall) ? new HoldAudioPlayer(this._callSession, this._holdAudioChunks) : null;
2269
2338
  player?.start();
2270
2339
  let result;
2271
2340
  try {
@@ -2316,8 +2385,8 @@ var PipelineSession = class {
2316
2385
  sampleRate: this._sampleRate
2317
2386
  })) {
2318
2387
  if (!this._running || !this._speaking) break;
2319
- const pcm8k = chunkXAOA3XFQ_cjs.resamplePcm16(audioChunk, this._sampleRate, 8e3);
2320
- const ulaw = chunkXAOA3XFQ_cjs.pcm16ToUlaw(pcm8k);
2388
+ const pcm8k = chunkQD2ZY4UP_cjs.resamplePcm16(audioChunk, this._sampleRate, 8e3);
2389
+ const ulaw = chunkQD2ZY4UP_cjs.pcm16ToUlaw(pcm8k);
2321
2390
  for (let off = 0; off < ulaw.length; off += 160) {
2322
2391
  let chunk = ulaw.subarray(off, off + 160);
2323
2392
  if (chunk.length < 160) {
@@ -2344,7 +2413,7 @@ var OpenAIRealtime = class {
2344
2413
  _language;
2345
2414
  _turnDetection;
2346
2415
  _greeting;
2347
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
2416
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
2348
2417
  _builtinTools = null;
2349
2418
  /**
2350
2419
  * 마지막 session.update 로 LLM 에 알린 tool 이름들. attach() 가 이 값과 현재
@@ -2421,7 +2490,7 @@ var OpenAIRealtime = class {
2421
2490
  /** Open WS + session.update + (optional) response.create without a CallSession. */
2422
2491
  async prewarm(tools) {
2423
2492
  if (tools) this._tools = tools;
2424
- this._call = new chunkXAOA3XFQ_cjs.BufferingCall();
2493
+ this._call = new chunkQD2ZY4UP_cjs.BufferingCall();
2425
2494
  this._closed = false;
2426
2495
  this._playback = null;
2427
2496
  this._latestMediaTs = 0;
@@ -2463,7 +2532,7 @@ var OpenAIRealtime = class {
2463
2532
  this._resyncTools();
2464
2533
  const prev = this._call;
2465
2534
  this._call = callSession;
2466
- chunkXAOA3XFQ_cjs.attachBuffered(prev, callSession);
2535
+ chunkQD2ZY4UP_cjs.attachBuffered(prev, callSession);
2467
2536
  }
2468
2537
  async start(callSession, tools) {
2469
2538
  if (tools) this._tools = tools;
@@ -2524,7 +2593,7 @@ var OpenAIRealtime = class {
2524
2593
  /** Current tool schemas: user tools + builtin tools (flat realtime format). */
2525
2594
  _currentToolSchemas() {
2526
2595
  const toolSchemas = this._tools ? this._tools.toOpenAITools().map((t) => ({ type: "function", ...t.function })) : [];
2527
- toolSchemas.push(...chunkXAOA3XFQ_cjs.getBuiltinToolSchemas(this._builtinTools, "realtime"));
2596
+ toolSchemas.push(...chunkQD2ZY4UP_cjs.getBuiltinToolSchemas(this._builtinTools, "realtime"));
2528
2597
  return toolSchemas;
2529
2598
  }
2530
2599
  /**
@@ -2695,9 +2764,9 @@ var OpenAIRealtime = class {
2695
2764
  const controller = new AbortController();
2696
2765
  this._pendingToolCalls.set(callId, controller);
2697
2766
  try {
2698
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(funcName) && this._call && !(this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall)) {
2767
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(funcName) && this._call && !(this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall)) {
2699
2768
  const args = JSON.parse(item["arguments"] ?? "{}");
2700
- const result2 = await chunkXAOA3XFQ_cjs.executeBuiltinTool(funcName, args, this._call);
2769
+ const result2 = await chunkQD2ZY4UP_cjs.executeBuiltinTool(funcName, args, this._call);
2701
2770
  if (result2 !== null) {
2702
2771
  if (funcName === "hang_up") return;
2703
2772
  if (controller.signal.aborted) return;
@@ -2714,7 +2783,7 @@ var OpenAIRealtime = class {
2714
2783
  return;
2715
2784
  }
2716
2785
  }
2717
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(funcName) && this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall) {
2786
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(funcName) && this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall) {
2718
2787
  this._log.warn("Builtin tool %s called before answer \u2014 deferring", funcName);
2719
2788
  await this._waitForResponseDone();
2720
2789
  this._send({
@@ -2722,7 +2791,7 @@ var OpenAIRealtime = class {
2722
2791
  item: {
2723
2792
  type: "function_call_output",
2724
2793
  call_id: callId,
2725
- output: chunkXAOA3XFQ_cjs.CALL_NOT_READY_RESULT
2794
+ output: chunkQD2ZY4UP_cjs.CALL_NOT_READY_RESULT
2726
2795
  }
2727
2796
  });
2728
2797
  this._send({ type: "response.create" });
@@ -2743,7 +2812,7 @@ var OpenAIRealtime = class {
2743
2812
  return;
2744
2813
  }
2745
2814
  let result;
2746
- const player = this._holdAudioChunks && this._call && !(this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall) ? new HoldAudioPlayer(this._call, this._holdAudioChunks) : null;
2815
+ const player = this._holdAudioChunks && this._call && !(this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall) ? new HoldAudioPlayer(this._call, this._holdAudioChunks) : null;
2747
2816
  player?.start();
2748
2817
  try {
2749
2818
  const args = JSON.parse(item["arguments"] ?? "{}");
@@ -2892,7 +2961,7 @@ var GeminiRealtime = class _GeminiRealtime {
2892
2961
  _toolDrainTimer = null;
2893
2962
  _lastAudioTime = 0;
2894
2963
  _holdAudioChunks = null;
2895
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
2964
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
2896
2965
  constructor(options = {}) {
2897
2966
  this._apiKey = options.apiKey ?? process.env["GOOGLE_API_KEY"] ?? "";
2898
2967
  this._systemPrompt = options.systemPrompt ?? "";
@@ -2938,7 +3007,7 @@ var GeminiRealtime = class _GeminiRealtime {
2938
3007
  /** Open Live session (no CallSession). Audio deltas accumulate into BufferingCall until attach(). */
2939
3008
  async prewarm(tools) {
2940
3009
  if (tools) this._tools = tools;
2941
- this._call = new chunkXAOA3XFQ_cjs.BufferingCall();
3010
+ this._call = new chunkQD2ZY4UP_cjs.BufferingCall();
2942
3011
  this._closed = false;
2943
3012
  this._sentAudioChunks = 0;
2944
3013
  this._audioRemainder = Buffer.alloc(0);
@@ -2995,7 +3064,7 @@ var GeminiRealtime = class _GeminiRealtime {
2995
3064
  async attach(callSession) {
2996
3065
  const prev = this._call;
2997
3066
  this._call = callSession;
2998
- chunkXAOA3XFQ_cjs.attachBuffered(prev, callSession);
3067
+ chunkQD2ZY4UP_cjs.attachBuffered(prev, callSession);
2999
3068
  }
3000
3069
  async start(callSession, tools) {
3001
3070
  if (tools) this._tools = tools;
@@ -3004,8 +3073,8 @@ var GeminiRealtime = class _GeminiRealtime {
3004
3073
  }
3005
3074
  feedAudio(audio) {
3006
3075
  if (this._session && !this._closed) {
3007
- const pcm8k = chunkXAOA3XFQ_cjs.ulawToPcm16(audio);
3008
- const pcm16k = chunkXAOA3XFQ_cjs.resamplePcm16(pcm8k, 8e3, 16e3);
3076
+ const pcm8k = chunkQD2ZY4UP_cjs.ulawToPcm16(audio);
3077
+ const pcm16k = chunkQD2ZY4UP_cjs.resamplePcm16(pcm8k, 8e3, 16e3);
3009
3078
  this._session.sendRealtimeInput({
3010
3079
  audio: {
3011
3080
  data: Buffer.from(pcm16k).toString("base64"),
@@ -3049,7 +3118,7 @@ var GeminiRealtime = class _GeminiRealtime {
3049
3118
  t.function.parameters ?? { type: "object", properties: {} }
3050
3119
  )
3051
3120
  })) : [];
3052
- toolDefs.push(...chunkXAOA3XFQ_cjs.getBuiltinToolSchemas(this._builtinTools, "gemini"));
3121
+ toolDefs.push(...chunkQD2ZY4UP_cjs.getBuiltinToolSchemas(this._builtinTools, "gemini"));
3053
3122
  return toolDefs;
3054
3123
  }
3055
3124
  _handleMessage(msg) {
@@ -3109,8 +3178,8 @@ var GeminiRealtime = class _GeminiRealtime {
3109
3178
  _handleAudioData(b64Data) {
3110
3179
  if (!this._call) return;
3111
3180
  const pcm24k = Buffer.from(b64Data, "base64");
3112
- const pcm8k = chunkXAOA3XFQ_cjs.resamplePcm16(pcm24k, 24e3, 8e3);
3113
- const ulaw = chunkXAOA3XFQ_cjs.pcm16ToUlaw(pcm8k);
3181
+ const pcm8k = chunkQD2ZY4UP_cjs.resamplePcm16(pcm24k, 24e3, 8e3);
3182
+ const ulaw = chunkQD2ZY4UP_cjs.pcm16ToUlaw(pcm8k);
3114
3183
  const combined = Buffer.concat([this._audioRemainder, ulaw]);
3115
3184
  const chunkSize = 160;
3116
3185
  const fullEnd = Math.floor(combined.length / chunkSize) * chunkSize;
@@ -3153,7 +3222,7 @@ var GeminiRealtime = class _GeminiRealtime {
3153
3222
  const functionCalls = toolCall.functionCalls;
3154
3223
  if (!functionCalls) return;
3155
3224
  const responses = [];
3156
- const player = this._holdAudioChunks && this._call && !(this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall) ? new HoldAudioPlayer(this._call, this._holdAudioChunks) : null;
3225
+ const player = this._holdAudioChunks && this._call && !(this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall) ? new HoldAudioPlayer(this._call, this._holdAudioChunks) : null;
3157
3226
  player?.start();
3158
3227
  try {
3159
3228
  for (const fc of functionCalls) {
@@ -3161,8 +3230,8 @@ var GeminiRealtime = class _GeminiRealtime {
3161
3230
  const fcId = fc.id ?? "";
3162
3231
  const args = fc.args ?? {};
3163
3232
  this._log.info({ tool: name, args }, "Tool call: %s", name);
3164
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(name) && this._call && !(this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall)) {
3165
- const result = await chunkXAOA3XFQ_cjs.executeBuiltinTool(
3233
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(name) && this._call && !(this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall)) {
3234
+ const result = await chunkQD2ZY4UP_cjs.executeBuiltinTool(
3166
3235
  name,
3167
3236
  args,
3168
3237
  this._call
@@ -3177,9 +3246,9 @@ var GeminiRealtime = class _GeminiRealtime {
3177
3246
  continue;
3178
3247
  }
3179
3248
  }
3180
- if (chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES.has(name) && this._call instanceof chunkXAOA3XFQ_cjs.BufferingCall) {
3249
+ if (chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES.has(name) && this._call instanceof chunkQD2ZY4UP_cjs.BufferingCall) {
3181
3250
  this._log.warn("Builtin tool %s called before answer \u2014 deferring", name);
3182
- responses.push({ id: fcId, name, response: { result: chunkXAOA3XFQ_cjs.CALL_NOT_READY_RESULT } });
3251
+ responses.push({ id: fcId, name, response: { result: chunkQD2ZY4UP_cjs.CALL_NOT_READY_RESULT } });
3183
3252
  continue;
3184
3253
  }
3185
3254
  if (!this._tools || !this._tools.has(name)) {
@@ -3224,7 +3293,7 @@ var GeminiRealtime = class _GeminiRealtime {
3224
3293
  // src/agent/pipeline/stt/deepgram-stt.ts
3225
3294
  var DeepgramSTT = class {
3226
3295
  _options;
3227
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
3296
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
3228
3297
  get provider() {
3229
3298
  return "deepgram";
3230
3299
  }
@@ -3351,7 +3420,7 @@ var DeepgramSTT = class {
3351
3420
  // src/agent/pipeline/tts/elevenlabs-tts.ts
3352
3421
  var ElevenLabsTTS = class {
3353
3422
  _options;
3354
- _log = chunkXAOA3XFQ_cjs.NOOP_LOGGER;
3423
+ _log = chunkQD2ZY4UP_cjs.NOOP_LOGGER;
3355
3424
  get provider() {
3356
3425
  return "elevenlabs";
3357
3426
  }
@@ -4097,47 +4166,47 @@ function mcpServerHTTP(options) {
4097
4166
 
4098
4167
  Object.defineProperty(exports, "BUILTIN_TOOL_NAMES", {
4099
4168
  enumerable: true,
4100
- get: function () { return chunkXAOA3XFQ_cjs.BUILTIN_TOOL_NAMES; }
4169
+ get: function () { return chunkQD2ZY4UP_cjs.BUILTIN_TOOL_NAMES; }
4101
4170
  });
4102
4171
  Object.defineProperty(exports, "BuiltinTool", {
4103
4172
  enumerable: true,
4104
- get: function () { return chunkXAOA3XFQ_cjs.BuiltinTool; }
4173
+ get: function () { return chunkQD2ZY4UP_cjs.BuiltinTool; }
4105
4174
  });
4106
4175
  Object.defineProperty(exports, "DECODE_TABLE", {
4107
4176
  enumerable: true,
4108
- get: function () { return chunkXAOA3XFQ_cjs.DECODE_TABLE; }
4177
+ get: function () { return chunkQD2ZY4UP_cjs.DECODE_TABLE; }
4109
4178
  });
4110
4179
  Object.defineProperty(exports, "createAgentLogger", {
4111
4180
  enumerable: true,
4112
- get: function () { return chunkXAOA3XFQ_cjs.createAgentLogger; }
4181
+ get: function () { return chunkQD2ZY4UP_cjs.createAgentLogger; }
4113
4182
  });
4114
4183
  Object.defineProperty(exports, "createPipelineLogger", {
4115
4184
  enumerable: true,
4116
- get: function () { return chunkXAOA3XFQ_cjs.createPipelineLogger; }
4185
+ get: function () { return chunkQD2ZY4UP_cjs.createPipelineLogger; }
4117
4186
  });
4118
4187
  Object.defineProperty(exports, "executeBuiltinTool", {
4119
4188
  enumerable: true,
4120
- get: function () { return chunkXAOA3XFQ_cjs.executeBuiltinTool; }
4189
+ get: function () { return chunkQD2ZY4UP_cjs.executeBuiltinTool; }
4121
4190
  });
4122
4191
  Object.defineProperty(exports, "getBuiltinToolSchemas", {
4123
4192
  enumerable: true,
4124
- get: function () { return chunkXAOA3XFQ_cjs.getBuiltinToolSchemas; }
4193
+ get: function () { return chunkQD2ZY4UP_cjs.getBuiltinToolSchemas; }
4125
4194
  });
4126
4195
  Object.defineProperty(exports, "isBuiltinTool", {
4127
4196
  enumerable: true,
4128
- get: function () { return chunkXAOA3XFQ_cjs.isBuiltinTool; }
4197
+ get: function () { return chunkQD2ZY4UP_cjs.isBuiltinTool; }
4129
4198
  });
4130
4199
  Object.defineProperty(exports, "pcm16ToUlaw", {
4131
4200
  enumerable: true,
4132
- get: function () { return chunkXAOA3XFQ_cjs.pcm16ToUlaw; }
4201
+ get: function () { return chunkQD2ZY4UP_cjs.pcm16ToUlaw; }
4133
4202
  });
4134
4203
  Object.defineProperty(exports, "resamplePcm16", {
4135
4204
  enumerable: true,
4136
- get: function () { return chunkXAOA3XFQ_cjs.resamplePcm16; }
4205
+ get: function () { return chunkQD2ZY4UP_cjs.resamplePcm16; }
4137
4206
  });
4138
4207
  Object.defineProperty(exports, "ulawToPcm16", {
4139
4208
  enumerable: true,
4140
- get: function () { return chunkXAOA3XFQ_cjs.ulawToPcm16; }
4209
+ get: function () { return chunkQD2ZY4UP_cjs.ulawToPcm16; }
4141
4210
  });
4142
4211
  exports.AnthropicLLM = AnthropicLLM;
4143
4212
  exports.AudioRecorder = AudioRecorder;