@teamlearners/clawops 0.21.0 → 0.23.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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkTRLJ6I3F_cjs = require('../chunk-TRLJ6I3F.cjs');
3
+ var chunkNXMTLS2U_cjs = require('../chunk-NXMTLS2U.cjs');
4
4
  var pino = require('pino');
5
5
  var fs = require('fs');
6
6
  var path = require('path');
@@ -1079,7 +1079,7 @@ var MAX_ERROR_MESSAGE_LENGTH = 200;
1079
1079
  function getSdkInfo() {
1080
1080
  return {
1081
1081
  name: "clawops-node",
1082
- version: chunkTRLJ6I3F_cjs.VERSION,
1082
+ version: chunkNXMTLS2U_cjs.VERSION,
1083
1083
  runtime: `node/${process.versions.node}`,
1084
1084
  os: `${process.platform}/${os__default.default.arch()}`
1085
1085
  };
@@ -1274,13 +1274,22 @@ var CallSession = class {
1274
1274
  }
1275
1275
  }
1276
1276
  }
1277
- /** Transfer the call to another destination. */
1277
+ /**
1278
+ * Transfer the call to a phone number or SIP endpoint.
1279
+ *
1280
+ * destinationType='pstn' (default): `to` is a phone number dialed via carrier.
1281
+ * destinationType='sip': `to` is a SIP URI (e.g. `sip:user@host`) connected
1282
+ * directly to a SIP endpoint without going through the PSTN carrier. Requires the
1283
+ * account to have an active `sip_trunk` add-on; otherwise the transfer fails and
1284
+ * the call continues with the AI (result `{ status: 'failed', ... }`).
1285
+ */
1278
1286
  async transfer(to, options) {
1279
1287
  if (!this._transferFn) {
1280
1288
  throw new Error("transfer not available");
1281
1289
  }
1282
1290
  return this._transferFn({
1283
1291
  to,
1292
+ destinationType: options?.destinationType ?? "pstn",
1284
1293
  mode: options?.mode ?? "blind",
1285
1294
  afterTransfer: options?.afterTransfer ?? "terminate",
1286
1295
  holdMedia: options?.holdMedia ?? "ringback",
@@ -1764,10 +1773,12 @@ var ClawOpsAgent = class _ClawOpsAgent {
1764
1773
  /** prewarm 세션이 실제 CallSession 에 attach 완료된 callId. attached 이후의 stop() 은 정상 종료 경로가 책임진다. */
1765
1774
  _prewarmAttached = /* @__PURE__ */ new Set();
1766
1775
  _prewarmEnabled;
1776
+ /** 모든 발신에 적용되는 AMD default. call() 인자로 호출별 override 가능. */
1777
+ _machineDetection;
1767
1778
  constructor(options) {
1768
1779
  this._apiKey = options.apiKey ?? process.env["CLAWOPS_API_KEY"] ?? "";
1769
1780
  this._accountId = options.accountId ?? process.env["CLAWOPS_ACCOUNT_ID"] ?? "";
1770
- this._baseUrl = options.baseUrl ?? chunkTRLJ6I3F_cjs.DEFAULT_BASE_URL;
1781
+ this._baseUrl = options.baseUrl ?? chunkNXMTLS2U_cjs.DEFAULT_BASE_URL;
1771
1782
  this._fromNumber = options.from;
1772
1783
  this._session = options.session;
1773
1784
  this._recording = options.recording ?? false;
@@ -1778,6 +1789,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1778
1789
  this._rxGain = _ClawOpsAgent._validateGain("rxGain", options.rxGain ?? 1);
1779
1790
  this._txGain = _ClawOpsAgent._validateGain("txGain", options.txGain ?? 1);
1780
1791
  this._prewarmEnabled = options.prewarmEnabled ?? true;
1792
+ this._machineDetection = options.machineDetection;
1781
1793
  if (options.tracing) {
1782
1794
  setTracingConfig(options.tracing);
1783
1795
  }
@@ -1790,7 +1802,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1790
1802
  }
1791
1803
  static _validateGain(name, gain) {
1792
1804
  if (typeof gain !== "number" || !Number.isFinite(gain) || gain < 0) {
1793
- throw new chunkTRLJ6I3F_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1805
+ throw new chunkNXMTLS2U_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1794
1806
  }
1795
1807
  return gain;
1796
1808
  }
@@ -1804,7 +1816,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1804
1816
  tool(nameOrTool, description, parameters, handler) {
1805
1817
  if (typeof nameOrTool === "string") {
1806
1818
  if (!description || !parameters || !handler) {
1807
- throw new chunkTRLJ6I3F_cjs.AgentError(
1819
+ throw new chunkNXMTLS2U_cjs.AgentError(
1808
1820
  "tool(name, description, parameters, handler) requires all arguments."
1809
1821
  );
1810
1822
  }
@@ -1840,10 +1852,10 @@ var ClawOpsAgent = class _ClawOpsAgent {
1840
1852
  async connect() {
1841
1853
  if (this._controlWs) return;
1842
1854
  if (!this._apiKey) {
1843
- throw new chunkTRLJ6I3F_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1855
+ throw new chunkNXMTLS2U_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1844
1856
  }
1845
1857
  if (!this._accountId) {
1846
- throw new chunkTRLJ6I3F_cjs.AgentError(
1858
+ throw new chunkNXMTLS2U_cjs.AgentError(
1847
1859
  "Account ID is required. Set CLAWOPS_ACCOUNT_ID or pass accountId option."
1848
1860
  );
1849
1861
  }
@@ -1867,7 +1879,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1867
1879
  } catch {
1868
1880
  }
1869
1881
  } catch (err) {
1870
- throw new chunkTRLJ6I3F_cjs.AgentConnectionError(
1882
+ throw new chunkNXMTLS2U_cjs.AgentConnectionError(
1871
1883
  `Failed to connect to ClawOps: ${err instanceof Error ? err.message : String(err)}`
1872
1884
  );
1873
1885
  }
@@ -1906,6 +1918,8 @@ var ClawOpsAgent = class _ClawOpsAgent {
1906
1918
  *
1907
1919
  * @param options.machineDetection 자동응답기/음성사서함 감지(AMD).
1908
1920
  * `'Enable'`=감지 후 `AnsweredBy` 통보(통화 계속), `'Hangup'`=음성사서함 감지 시 자동 종료.
1921
+ * 미지정 시 인스턴스 default(생성자의 `machineDetection`)를 따른다.
1922
+ * 우선순위: 호출 인자 > 인스턴스 default > 비활성.
1909
1923
  */
1910
1924
  async call(to, options) {
1911
1925
  await this.connect();
@@ -1915,8 +1929,9 @@ var ClawOpsAgent = class _ClawOpsAgent {
1915
1929
  From: this._fromNumber,
1916
1930
  Timeout: options?.timeout ?? 60
1917
1931
  };
1918
- if (options?.machineDetection) {
1919
- body["MachineDetection"] = options.machineDetection;
1932
+ const effectiveMd = options?.machineDetection ?? this._machineDetection;
1933
+ if (effectiveMd) {
1934
+ body["MachineDetection"] = effectiveMd;
1920
1935
  }
1921
1936
  const resp = await fetch(url, {
1922
1937
  method: "POST",
@@ -1928,7 +1943,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1928
1943
  });
1929
1944
  if (resp.status !== 201) {
1930
1945
  const error = await resp.json();
1931
- throw new chunkTRLJ6I3F_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1946
+ throw new chunkNXMTLS2U_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1932
1947
  }
1933
1948
  const data = await resp.json();
1934
1949
  const callSession = new CallSession({
@@ -2361,11 +2376,12 @@ var SEND_DTMF = {
2361
2376
  };
2362
2377
  var TRANSFER_CALL = {
2363
2378
  name: "transfer_call",
2364
- description: "Transfer the current call to another phone number. Use for blind transfer (direct handoff) or warm transfer (with whisper message to the target).",
2379
+ 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).",
2365
2380
  parameters: {
2366
2381
  type: "object",
2367
2382
  properties: {
2368
- to: { type: "string", description: "Phone number to transfer to" },
2383
+ 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'." },
2384
+ 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)." },
2369
2385
  mode: { type: "string", enum: ["blind", "warm"], description: "blind: direct transfer (default), warm: play whisper to target first" },
2370
2386
  after_transfer: { type: "string", enum: ["terminate", "return"], description: "terminate: end AI session (default), return: AI resumes after transfer ends" },
2371
2387
  whisper: { type: "string", description: "Message to speak to transfer target before connecting customer (warm mode only)" },
@@ -2455,6 +2471,7 @@ async function executeBuiltinTool(funcName, args, call) {
2455
2471
  if (funcName === "transfer_call") {
2456
2472
  try {
2457
2473
  call.transfer(args["to"], {
2474
+ destinationType: args["destination_type"] ?? void 0,
2458
2475
  mode: args["mode"] ?? void 0,
2459
2476
  afterTransfer: args["after_transfer"] ?? void 0,
2460
2477
  whisper: args["whisper"] ?? void 0,