@teamlearners/clawops 0.24.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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkLUA53NPZ_cjs = require('../chunk-LUA53NPZ.cjs');
3
+ var chunkIVJXHNUN_cjs = require('../chunk-IVJXHNUN.cjs');
4
4
  var chunkU4UFTVLX_cjs = require('../chunk-U4UFTVLX.cjs');
5
5
  var fs = require('fs');
6
6
  var path = require('path');
@@ -728,7 +728,7 @@ var MAX_ERROR_MESSAGE_LENGTH = 200;
728
728
  function getSdkInfo() {
729
729
  return {
730
730
  name: "clawops-node",
731
- version: chunkLUA53NPZ_cjs.VERSION,
731
+ version: chunkIVJXHNUN_cjs.VERSION,
732
732
  runtime: `node/${process.versions.node}`,
733
733
  os: `${process.platform}/${os__default.default.arch()}`
734
734
  };
@@ -764,6 +764,7 @@ var CallSession = class {
764
764
  startTime;
765
765
  metadata;
766
766
  _status;
767
+ _endedStatus = null;
767
768
  _sendAudioFn = null;
768
769
  _clearAudioFn = null;
769
770
  _hangupFn = null;
@@ -812,6 +813,17 @@ var CallSession = class {
812
813
  get status() {
813
814
  return this._status;
814
815
  }
816
+ /**
817
+ * 서버가 통보한 최종 종료 상태. 통화가 끝나기 전에는 null.
818
+ *
819
+ * `completed`(성사) / `no-answer`(벨은 울렸으나 무응답) / `busy`(통화중) /
820
+ * `rejected`(수신 거절) / `canceled`(응답 전 발신 측 취소) / `failed`(시스템·망 오류).
821
+ * `status` 는 SDK 내부 수명주기(ringing→active→ended)이므로 통화 성사 여부는
822
+ * 이 값이나 `call_failed` 이벤트로 판단한다.
823
+ */
824
+ get endedStatus() {
825
+ return this._endedStatus;
826
+ }
815
827
  get duration() {
816
828
  return (Date.now() - this.startTime.getTime()) / 1e3;
817
829
  }
@@ -972,8 +984,20 @@ var CallSession = class {
972
984
  async wait() {
973
985
  return this._endedPromise;
974
986
  }
975
- /** Mark the session as ended (called internally). */
976
- _markEnded() {
987
+ /**
988
+ * Mark the session as ended (called internally).
989
+ *
990
+ * @param status 서버가 통보한 최종 상태(completed/no-answer/busy/rejected/canceled/
991
+ * failed). 주어지면 `endedStatus` 로 확정한다 — 상대가 받지 않은 통화를 성사된 통화와
992
+ * 구분하기 위함이다. 생략하면 미디어 세션 정리 경로에서의 호출이므로, 아직 종료 전일
993
+ * 때만 'completed' 로 채우고 이미 확정된 서버 상태는 덮어쓰지 않는다.
994
+ */
995
+ _markEnded(status) {
996
+ if (status !== void 0) {
997
+ this._endedStatus = status;
998
+ } else if (this._status !== "ended") {
999
+ this._endedStatus = "completed";
1000
+ }
977
1001
  this._status = "ended";
978
1002
  this._resolveEnded();
979
1003
  }
@@ -1409,7 +1433,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1409
1433
  constructor(options) {
1410
1434
  this._apiKey = options.apiKey ?? process.env["CLAWOPS_API_KEY"] ?? "";
1411
1435
  this._accountId = options.accountId ?? process.env["CLAWOPS_ACCOUNT_ID"] ?? "";
1412
- this._baseUrl = options.baseUrl ?? chunkLUA53NPZ_cjs.DEFAULT_BASE_URL;
1436
+ this._baseUrl = options.baseUrl ?? chunkIVJXHNUN_cjs.DEFAULT_BASE_URL;
1413
1437
  this._fromNumber = options.from;
1414
1438
  this._session = options.session;
1415
1439
  this._recording = options.recording ?? false;
@@ -1433,7 +1457,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1433
1457
  }
1434
1458
  static _validateGain(name, gain) {
1435
1459
  if (typeof gain !== "number" || !Number.isFinite(gain) || gain < 0) {
1436
- throw new chunkLUA53NPZ_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1460
+ throw new chunkIVJXHNUN_cjs.AgentError(`${name}=${gain} must be a finite number >= 0`);
1437
1461
  }
1438
1462
  return gain;
1439
1463
  }
@@ -1447,7 +1471,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1447
1471
  tool(nameOrTool, description, parameters, handler) {
1448
1472
  if (typeof nameOrTool === "string") {
1449
1473
  if (!description || !parameters || !handler) {
1450
- throw new chunkLUA53NPZ_cjs.AgentError(
1474
+ throw new chunkIVJXHNUN_cjs.AgentError(
1451
1475
  "tool(name, description, parameters, handler) requires all arguments."
1452
1476
  );
1453
1477
  }
@@ -1483,10 +1507,10 @@ var ClawOpsAgent = class _ClawOpsAgent {
1483
1507
  async connect() {
1484
1508
  if (this._controlWs) return;
1485
1509
  if (!this._apiKey) {
1486
- throw new chunkLUA53NPZ_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1510
+ throw new chunkIVJXHNUN_cjs.AgentError("API key is required. Set CLAWOPS_API_KEY or pass apiKey option.");
1487
1511
  }
1488
1512
  if (!this._accountId) {
1489
- throw new chunkLUA53NPZ_cjs.AgentError(
1513
+ throw new chunkIVJXHNUN_cjs.AgentError(
1490
1514
  "Account ID is required. Set CLAWOPS_ACCOUNT_ID or pass accountId option."
1491
1515
  );
1492
1516
  }
@@ -1510,7 +1534,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1510
1534
  } catch {
1511
1535
  }
1512
1536
  } catch (err) {
1513
- throw new chunkLUA53NPZ_cjs.AgentConnectionError(
1537
+ throw new chunkIVJXHNUN_cjs.AgentConnectionError(
1514
1538
  `Failed to connect to ClawOps: ${err instanceof Error ? err.message : String(err)}`
1515
1539
  );
1516
1540
  }
@@ -1574,7 +1598,7 @@ var ClawOpsAgent = class _ClawOpsAgent {
1574
1598
  });
1575
1599
  if (resp.status !== 201) {
1576
1600
  const error = await resp.json();
1577
- throw new chunkLUA53NPZ_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1601
+ throw new chunkIVJXHNUN_cjs.AgentError(`\uBC1C\uC2E0 \uC2E4\uD328 (${resp.status}): ${error["error"] ?? ""}`);
1578
1602
  }
1579
1603
  const data = await resp.json();
1580
1604
  const callSession = new CallSession({
@@ -1625,10 +1649,15 @@ var ClawOpsAgent = class _ClawOpsAgent {
1625
1649
  }
1626
1650
  _handleEnded(event) {
1627
1651
  const callId = event["callId"];
1652
+ const status = event["status"] || "completed";
1628
1653
  const session = this._activeSessions.get(callId);
1629
1654
  if (session) {
1630
- this._log.info("Call ended (server): %s", callId);
1631
- session._markEnded();
1655
+ this._log.info("Call ended (server): %s (status=%s)", callId, status);
1656
+ if (status !== "completed") {
1657
+ this._log.info("Outbound call not connected: %s (%s)", callId, status);
1658
+ session._emit("call_failed", status);
1659
+ }
1660
+ session._markEnded(status);
1632
1661
  this._activeSessions.delete(callId);
1633
1662
  }
1634
1663
  void this._cleanupPrewarm(callId);
@@ -1740,9 +1769,10 @@ var ClawOpsAgent = class _ClawOpsAgent {
1740
1769
  const callId = event["callId"];
1741
1770
  const session = this._activeSessions.get(callId);
1742
1771
  if (session) {
1743
- this._log.info("Outbound call failed: %s (%s)", callId, event["reason"] ?? "failed");
1744
- session._emit("call_failed", event["reason"] ?? "failed");
1745
- session._markEnded();
1772
+ const reason = event["reason"] ?? "failed";
1773
+ this._log.info("Outbound call failed: %s (%s)", callId, reason);
1774
+ session._emit("call_failed", reason);
1775
+ session._markEnded(reason);
1746
1776
  this._activeSessions.delete(callId);
1747
1777
  }
1748
1778
  void this._cleanupPrewarm(callId);