@teamlearners/clawops 0.38.0 → 0.40.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/README.md +96 -0
- package/dist/agent/index.cjs +77 -77
- package/dist/agent/index.js +4 -4
- package/dist/agent/livekit/index.cjs +9 -9
- package/dist/agent/livekit/index.js +2 -2
- package/dist/{chunk-EO25KTL4.js → chunk-AYSW63CJ.js} +3 -3
- package/dist/{chunk-EO25KTL4.js.map → chunk-AYSW63CJ.js.map} +1 -1
- package/dist/chunk-IEFCBBKV.cjs +8 -0
- package/dist/{chunk-NXCYAYFT.cjs.map → chunk-IEFCBBKV.cjs.map} +1 -1
- package/dist/{chunk-IYSPOOKH.cjs → chunk-MXEZQRIL.cjs} +2 -2
- package/dist/chunk-MXEZQRIL.cjs.map +1 -0
- package/dist/{chunk-ASQU6NA2.cjs → chunk-PO5ACGWL.cjs} +4 -4
- package/dist/{chunk-ASQU6NA2.cjs.map → chunk-PO5ACGWL.cjs.map} +1 -1
- package/dist/chunk-R6UEIVYE.js +6 -0
- package/dist/{chunk-J7UIB4EA.js.map → chunk-R6UEIVYE.js.map} +1 -1
- package/dist/{chunk-VYGIWHRU.js → chunk-SXXOAPMG.js} +2 -2
- package/dist/chunk-SXXOAPMG.js.map +1 -0
- package/dist/{client-ZOgpzAPe.d.cts → client-DOMZ2phc.d.cts} +301 -13
- package/dist/{client-ZOgpzAPe.d.ts → client-DOMZ2phc.d.ts} +301 -13
- package/dist/index.cjs +184 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +155 -14
- package/dist/index.js.map +1 -1
- package/dist/solapi/index.cjs +7 -7
- package/dist/solapi/index.d.cts +2 -2
- package/dist/solapi/index.d.ts +2 -2
- package/dist/solapi/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-IYSPOOKH.cjs.map +0 -1
- package/dist/chunk-J7UIB4EA.js +0 -6
- package/dist/chunk-NXCYAYFT.cjs +0 -8
- package/dist/chunk-VYGIWHRU.js.map +0 -1
package/dist/solapi/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXEZQRIL_cjs = require('../chunk-MXEZQRIL.cjs');
|
|
4
4
|
|
|
5
5
|
// src/solapi/_concurrency.ts
|
|
6
6
|
var DEFAULT_CONCURRENCY = 10;
|
|
@@ -312,7 +312,7 @@ function assertConfigSupported(config) {
|
|
|
312
312
|
if (config.scheduledDate !== void 0) unsupported.push("scheduledDate");
|
|
313
313
|
if (config.allowDuplicates === false) unsupported.push("allowDuplicates: false");
|
|
314
314
|
if (unsupported.length > 0) {
|
|
315
|
-
throw new
|
|
315
|
+
throw new chunkMXEZQRIL_cjs.SolapiBridgeError(
|
|
316
316
|
`ClawOps \uB85C \uBCF4\uB0B4\uB294 \uBA54\uC2DC\uC9C0\uC5D0\uB294 ${unsupported.join(", ")} \uB97C \uC801\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD574\uB2F9 \uC124\uC815\uC774 \uD544\uC694\uD55C \uBC1C\uC1A1\uC740 \uC194\uB77C\uD53C\uB85C \uBCF4\uB0B4\uAC70\uB098 \uD638\uCD9C\uC744 \uBD84\uB9AC\uD558\uC2ED\uC2DC\uC624.`
|
|
317
317
|
);
|
|
318
318
|
}
|
|
@@ -377,7 +377,7 @@ function partition(list) {
|
|
|
377
377
|
continue;
|
|
378
378
|
}
|
|
379
379
|
if (message.imageId !== void 0) {
|
|
380
|
-
throw new
|
|
380
|
+
throw new chunkMXEZQRIL_cjs.SolapiBridgeError(
|
|
381
381
|
"imageId \uB294 \uC194\uB77C\uD53C\uC5D0 \uC5C5\uB85C\uB4DC\uB41C \uD30C\uC77C ID \uB77C ClawOps \uB85C \uC804\uB2EC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uBBF8\uC9C0 \uCCA8\uBD80\uAC00 \uD544\uC694\uD558\uBA74 ClawOps \uC758 mediaUrl \uB85C \uC9C1\uC811 \uBC1C\uC1A1\uD558\uC2ED\uC2DC\uC624."
|
|
382
382
|
);
|
|
383
383
|
}
|
|
@@ -549,7 +549,7 @@ function makeSend(options, fallbackConfig, templateCache) {
|
|
|
549
549
|
if (forSolapi.length > 0) {
|
|
550
550
|
const solapi = options.solapi;
|
|
551
551
|
if (!solapi) {
|
|
552
|
-
throw new
|
|
552
|
+
throw new chunkMXEZQRIL_cjs.SolapiBridgeError(
|
|
553
553
|
"\uC54C\uB9BC\uD1A1\xB7RCS \uB97C \uBCF4\uB0B4\uB824\uBA74 solapi \uC778\uC2A4\uD134\uC2A4\uB97C \uB118\uACA8\uC57C \uD569\uB2C8\uB2E4. new ClawOpsMessageService({ solapi: new SolapiMessageService(key, secret), \u2026 })"
|
|
554
554
|
);
|
|
555
555
|
}
|
|
@@ -636,7 +636,7 @@ function create(options) {
|
|
|
636
636
|
const send = makeSend(options, fallbackConfig, templateCache);
|
|
637
637
|
if (fallbackConfig?.mode === "sweep") {
|
|
638
638
|
if (!options.solapi) {
|
|
639
|
-
throw new
|
|
639
|
+
throw new chunkMXEZQRIL_cjs.SolapiBridgeError(
|
|
640
640
|
"mode: 'sweep' \uC740 \uC194\uB77C\uD53C \uB9AC\uD3EC\uD2B8\uB97C \uD6D1\uB294 \uAE30\uB2A5\uC774\uB77C solapi \uC778\uC2A4\uD134\uC2A4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uBB38\uC790\uB9CC \uBCF4\uB0B8\uB2E4\uBA74 \uC774 \uC124\uC815\uC740 \uD560 \uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
641
641
|
);
|
|
642
642
|
}
|
|
@@ -657,7 +657,7 @@ function create(options) {
|
|
|
657
657
|
return Reflect.get(Object.prototype, property);
|
|
658
658
|
}
|
|
659
659
|
return () => {
|
|
660
|
-
throw new
|
|
660
|
+
throw new chunkMXEZQRIL_cjs.SolapiBridgeError(
|
|
661
661
|
`${String(property)}() \uB294 \uC194\uB77C\uD53C \uAE30\uB2A5\uC785\uB2C8\uB2E4. solapi \uC778\uC2A4\uD134\uC2A4\uB97C \uB118\uACA8\uC8FC\uC138\uC694.`
|
|
662
662
|
);
|
|
663
663
|
};
|
|
@@ -671,7 +671,7 @@ var ClawOpsMessageService = function(options) {
|
|
|
671
671
|
|
|
672
672
|
Object.defineProperty(exports, "SolapiBridgeError", {
|
|
673
673
|
enumerable: true,
|
|
674
|
-
get: function () { return
|
|
674
|
+
get: function () { return chunkMXEZQRIL_cjs.SolapiBridgeError; }
|
|
675
675
|
});
|
|
676
676
|
exports.CLAWOPS_FAILURE_STATUS_CODE = CLAWOPS_FAILURE_STATUS_CODE;
|
|
677
677
|
exports.ClawOpsMessageService = ClawOpsMessageService;
|
package/dist/solapi/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RequestSendMessagesSchema, SolapiMessageService } from 'solapi';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { I as ClawOps } from '../client-DOMZ2phc.cjs';
|
|
3
|
+
export { at as SolapiBridgeError } from '../client-DOMZ2phc.cjs';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
6
|
/** 제네릭을 거쳐야 유니온(단건 | 배열)에 분배된다 */
|
package/dist/solapi/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RequestSendMessagesSchema, SolapiMessageService } from 'solapi';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { I as ClawOps } from '../client-DOMZ2phc.js';
|
|
3
|
+
export { at as SolapiBridgeError } from '../client-DOMZ2phc.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
6
|
/** 제네릭을 거쳐야 유니온(단건 | 배열)에 분배된다 */
|
package/dist/solapi/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SolapiBridgeError } from '../chunk-
|
|
2
|
-
export { SolapiBridgeError } from '../chunk-
|
|
1
|
+
import { SolapiBridgeError } from '../chunk-SXXOAPMG.js';
|
|
2
|
+
export { SolapiBridgeError } from '../chunk-SXXOAPMG.js';
|
|
3
3
|
|
|
4
4
|
// src/solapi/_concurrency.ts
|
|
5
5
|
var DEFAULT_CONCURRENCY = 10;
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/error.ts"],"names":[],"mappings":";;;AAsDO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAEO,IAAM,QAAA,GAAN,cAAuB,YAAA,CAAa;AAAA,EAChC,OAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAA0C;AACrE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACF;AAEO,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA,EAClC,MAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAA;AAAA,EAET,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS,MAAA;AACvB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,UAAU,QAAA,CAAS,OAAA;AACxB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAiB,IAAI,CAAA;AAAA,EACnC;AACF;AAGA,SAAS,iBAAiB,IAAA,EAA6C;AACrE,EAAA,MAAM,OAAQ,IAAA,EAAgD,IAAA;AAC9D,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,KAAK,IAAA,GAAO,MAAA;AAC1D;AAEO,IAAM,eAAA,GAAN,cAA8B,cAAA,CAAe;AAAA,EAChC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,cAAA,CAAe;AAAA,EACpC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,qBAAA,GAAN,cAAoC,cAAA,CAAe;AAAA,EACtC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,cAAA,CAAe;AAAA,EAC9B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,cAAA,CAAe;AAAA,EAC9B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,wBAAA,GAAN,cAAuC,cAAA,CAAe;AAAA,EACzC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,0BAAA;AAAA,EACd;AACF;AAQO,IAAM,cAAA,GAAN,cAA6B,cAAA,CAAe;AAAA,EAC/B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,cAAA,CAAe;AAAA,EACpC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,uBAAA,GAAN,cAAsC,cAAA,CAAe;AAAA,EACxC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAEO,IAAM,kBAAA,GAAN,cAAiC,QAAA,CAAS;AAAA,EAC/C,WAAA,CAAY,OAAA,EAA0C,OAAA,GAAU,mBAAA,EAAqB;AACnF,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,kBAAA,CAAmB;AAAA,EACtD,YAAY,OAAA,EAA0C;AACpD,IAAA,KAAA,CAAM,SAAS,oBAAoB,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,0BAAA,GAAN,cAAyC,QAAA,CAAS;AAAA,EAC9C,MAAA;AAAA,EAET,WAAA,CAAY,UAA8B,OAAA,EAA0C;AAClF,IAAA,KAAA,CAAM,mCAAmC,OAAO,CAAA;AAChD,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AACZ,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS,MAAA;AAAA,EACzB;AACF;AAMO,IAAM,iBAAA,GAAN,cAAgC,YAAA,CAAa;AAAA,EAClD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAEO,IAAM,UAAA,GAAN,cAAyB,YAAA,CAAa;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AAAA,EACd;AACF;AAEO,IAAM,oBAAA,GAAN,cAAmC,UAAA,CAAW;AAAA,EACnD,WAAA,CAAY,UAAU,oCAAA,EAAsC;AAC1D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF;AAEA,IAAM,oBAAA,GAQF;AAAA,EACF,GAAA,EAAK,eAAA;AAAA,EACL,GAAA,EAAK,mBAAA;AAAA,EACL,GAAA,EAAK,qBAAA;AAAA,EACL,GAAA,EAAK,aAAA;AAAA,EACL,GAAA,EAAK,aAAA;AAAA,EACL,GAAA,EAAK,wBAAA;AAAA,EACL,GAAA,EAAK,cAAA;AAAA,EACL,GAAA,EAAK,mBAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAA;AAEO,SAAS,eAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,EACA,OAAA,EACgB;AAChB,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,WAAW,IAAA,EAAM;AACvD,IAAA,OAAA,GAAW,IAAA,CAA2B,KAAA;AAAA,EACxC,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,QAAQ,MAAM,CAAA,CAAA;AAAA,EAC1B;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAqB,MAAM,CAAA;AAC9C,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO,IAAI,WAAW,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AAAA,EACnE;AACA,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,OAAO,IAAI,oBAAoB,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AAAA,EAC5E;AACA,EAAA,OAAO,IAAI,eAAe,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AACvE","file":"chunk-IYSPOOKH.cjs","sourcesContent":["/**\n * 서버가 에러 응답의 `code` 로 싣는 값.\n *\n * 문구가 아니라 **이 값으로 분기한다** — 한글 메시지는 바뀔 수 있다.\n *\n * ⚠️ 문자 도메인은 snake_case, 카카오 채널 도메인은 SCREAMING_CASE 다. 서버가 실제로\n * 그렇게 보내므로 SDK 가 임의로 정규화하지 않는다. 열린 유니온이라 목록에 없는 코드도\n * 그대로 실린다(자동완성만 돕는다).\n */\nexport type ClawOpsErrorCode =\n // 발송 일반\n | 'invalid_phone'\n | 'invalid_type'\n | 'invalid_input'\n | 'from_not_registered'\n | 'body_too_long'\n | 'sms_no_subject'\n | 'sms_no_media'\n | 'lms_no_media'\n | 'too_many_media'\n | 'invalid_media_ext'\n | 'media_download_failed'\n | 'type_not_supported'\n | 'messaging_blocked'\n | 'recipient_blocked'\n | 'quota_exceeded'\n | 'override_quota_exceeded'\n | 'no_active_subscription'\n // 알림톡 발송\n | 'kakao_required'\n | 'kakao_type_conflict'\n | 'kakao_body_not_allowed'\n | 'kakao_subject_not_allowed'\n | 'kakao_media_not_allowed'\n | 'kakao_channel_not_found'\n | 'kakao_template_not_found'\n | 'kakao_template_not_approved'\n | 'kakao_template_dormant'\n | 'kakao_variable_missing'\n | 'kakao_variable_unknown'\n | 'kakao_send_failed'\n | 'kakao_unavailable'\n | 'invalid_fallback_type'\n // 카카오 채널 연동\n | 'KAKAO_TOKEN_INVALID'\n | 'KAKAO_CHANNEL_ALREADY_LINKED'\n | 'KAKAO_CHANNEL_REJECTED'\n | 'KAKAO_RATE_LIMITED'\n | 'KAKAO_PROVIDER_UNAVAILABLE'\n // 공통\n | 'VALIDATION'\n | 'NOT_FOUND'\n | (string & {});\n\nexport class ClawOpsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ClawOpsError';\n }\n}\n\nexport class APIError extends ClawOpsError {\n readonly request: { method: string; url: string };\n\n constructor(message: string, request: { method: string; url: string }) {\n super(message);\n this.name = 'APIError';\n this.request = request;\n }\n}\n\nexport class APIStatusError extends APIError {\n readonly status: number;\n readonly body: unknown;\n readonly headers: Headers | undefined;\n /**\n * 서버가 함께 보낸 기계 판독용 코드(`{ error, code }`). 없으면 undefined 다.\n *\n * 같은 상태 코드가 서로 다른 사유를 담는다 — 422 만 해도 수신거부(`recipient_blocked`)와\n * 할당량 초과(`quota_exceeded`)가 갈리고, 한글 문구로 구분하면 문구가 바뀔 때 깨진다.\n */\n readonly code: ClawOpsErrorCode | undefined;\n\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, request);\n this.name = 'APIStatusError';\n this.status = response.status;\n this.body = body;\n this.headers = response.headers;\n this.code = extractErrorCode(body);\n }\n}\n\n/** 응답 본문에서 `code` 를 꺼낸다. 문자열이 아니면 없는 것으로 본다. */\nfunction extractErrorCode(body: unknown): ClawOpsErrorCode | undefined {\n const code = (body as { code?: unknown } | null | undefined)?.code;\n return typeof code === 'string' && code !== '' ? code : undefined;\n}\n\nexport class BadRequestError extends APIStatusError {\n override readonly status = 400 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends APIStatusError {\n override readonly status = 401 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class PermissionDeniedError extends APIStatusError {\n override readonly status = 403 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'PermissionDeniedError';\n }\n}\n\nexport class NotFoundError extends APIStatusError {\n override readonly status = 404 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends APIStatusError {\n override readonly status = 409 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'ConflictError';\n }\n}\n\nexport class UnprocessableEntityError extends APIStatusError {\n override readonly status = 422 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * HTTP 429 Too Many Requests.\n *\n * 동시 통화 한도 초과 등 일시적 제한. SDK는 자동 재시도(최대 2회, 지수 backoff)를 수행한다.\n * 즉각 피드백이 필요하면 client 생성 시 maxRetries: 0으로 재시도를 비활성화하라.\n */\nexport class RateLimitError extends APIStatusError {\n override readonly status = 429 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'RateLimitError';\n }\n}\n\nexport class InternalServerError extends APIStatusError {\n override readonly status = 500 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'InternalServerError';\n }\n}\n\nexport class ServiceUnavailableError extends APIStatusError {\n override readonly status = 503 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'ServiceUnavailableError';\n }\n}\n\nexport class APIConnectionError extends APIError {\n constructor(request: { method: string; url: string }, message = 'Connection error.') {\n super(message, request);\n this.name = 'APIConnectionError';\n }\n}\n\nexport class APITimeoutError extends APIConnectionError {\n constructor(request: { method: string; url: string }) {\n super(request, 'Request timed out.');\n this.name = 'APITimeoutError';\n }\n}\n\nexport class APIResponseValidationError extends APIError {\n readonly status: number;\n\n constructor(response: { status: number }, request: { method: string; url: string }) {\n super('API response validation failed.', request);\n this.name = 'APIResponseValidationError';\n this.status = response.status;\n }\n}\n\n/**\n * 솔라피 호환 레이어가 호출을 거절할 때 쓴다.\n * 조용히 다르게 동작하느니 여기서 멈추는 편이 낫다고 판단한 경우들이다.\n */\nexport class SolapiBridgeError extends ClawOpsError {\n constructor(message: string) {\n super(message);\n this.name = 'SolapiBridgeError';\n }\n}\n\nexport class AgentError extends ClawOpsError {\n constructor(message: string) {\n super(message);\n this.name = 'AgentError';\n }\n}\n\nexport class AgentConnectionError extends AgentError {\n constructor(message = 'Agent WebSocket connection failed.') {\n super(message);\n this.name = 'AgentConnectionError';\n }\n}\n\nconst STATUS_CODE_TO_ERROR: Record<\n number,\n new (\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) => APIStatusError\n> = {\n 400: BadRequestError,\n 401: AuthenticationError,\n 403: PermissionDeniedError,\n 404: NotFoundError,\n 409: ConflictError,\n 422: UnprocessableEntityError,\n 429: RateLimitError,\n 500: InternalServerError,\n 503: ServiceUnavailableError,\n};\n\nexport function makeStatusError(\n status: number,\n body: unknown,\n headers: Headers | undefined,\n request: { method: string; url: string },\n): APIStatusError {\n let message = '';\n if (body && typeof body === 'object' && 'error' in body) {\n message = (body as { error: string }).error;\n } else {\n message = `HTTP ${status}`;\n }\n\n const ErrorClass = STATUS_CODE_TO_ERROR[status];\n if (ErrorClass) {\n return new ErrorClass(message, { status, headers }, body, request);\n }\n if (status >= 500) {\n return new InternalServerError(message, { status, headers }, body, request);\n }\n return new APIStatusError(message, { status, headers }, body, request);\n}\n"]}
|
package/dist/chunk-J7UIB4EA.js
DELETED
package/dist/chunk-NXCYAYFT.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/error.ts"],"names":[],"mappings":";AAsDO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAEO,IAAM,QAAA,GAAN,cAAuB,YAAA,CAAa;AAAA,EAChC,OAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAA0C;AACrE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACF;AAEO,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA,EAClC,MAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAA;AAAA,EAET,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS,MAAA;AACvB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,UAAU,QAAA,CAAS,OAAA;AACxB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAiB,IAAI,CAAA;AAAA,EACnC;AACF;AAGA,SAAS,iBAAiB,IAAA,EAA6C;AACrE,EAAA,MAAM,OAAQ,IAAA,EAAgD,IAAA;AAC9D,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,KAAK,IAAA,GAAO,MAAA;AAC1D;AAEO,IAAM,eAAA,GAAN,cAA8B,cAAA,CAAe;AAAA,EAChC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,cAAA,CAAe;AAAA,EACpC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,qBAAA,GAAN,cAAoC,cAAA,CAAe;AAAA,EACtC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,cAAA,CAAe;AAAA,EAC9B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,cAAA,CAAe;AAAA,EAC9B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,wBAAA,GAAN,cAAuC,cAAA,CAAe;AAAA,EACzC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,0BAAA;AAAA,EACd;AACF;AAQO,IAAM,cAAA,GAAN,cAA6B,cAAA,CAAe;AAAA,EAC/B,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,cAAA,CAAe;AAAA,EACpC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,uBAAA,GAAN,cAAsC,cAAA,CAAe;AAAA,EACxC,MAAA,GAAS,GAAA;AAAA,EAC3B,WAAA,CACE,OAAA,EACA,QAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAEO,IAAM,kBAAA,GAAN,cAAiC,QAAA,CAAS;AAAA,EAC/C,WAAA,CAAY,OAAA,EAA0C,OAAA,GAAU,mBAAA,EAAqB;AACnF,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,kBAAA,CAAmB;AAAA,EACtD,YAAY,OAAA,EAA0C;AACpD,IAAA,KAAA,CAAM,SAAS,oBAAoB,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,0BAAA,GAAN,cAAyC,QAAA,CAAS;AAAA,EAC9C,MAAA;AAAA,EAET,WAAA,CAAY,UAA8B,OAAA,EAA0C;AAClF,IAAA,KAAA,CAAM,mCAAmC,OAAO,CAAA;AAChD,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AACZ,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS,MAAA;AAAA,EACzB;AACF;AAMO,IAAM,iBAAA,GAAN,cAAgC,YAAA,CAAa;AAAA,EAClD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAEO,IAAM,UAAA,GAAN,cAAyB,YAAA,CAAa;AAAA,EAC3C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AAAA,EACd;AACF;AAEO,IAAM,oBAAA,GAAN,cAAmC,UAAA,CAAW;AAAA,EACnD,WAAA,CAAY,UAAU,oCAAA,EAAsC;AAC1D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF;AAEA,IAAM,oBAAA,GAQF;AAAA,EACF,GAAA,EAAK,eAAA;AAAA,EACL,GAAA,EAAK,mBAAA;AAAA,EACL,GAAA,EAAK,qBAAA;AAAA,EACL,GAAA,EAAK,aAAA;AAAA,EACL,GAAA,EAAK,aAAA;AAAA,EACL,GAAA,EAAK,wBAAA;AAAA,EACL,GAAA,EAAK,cAAA;AAAA,EACL,GAAA,EAAK,mBAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAA;AAEO,SAAS,eAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,EACA,OAAA,EACgB;AAChB,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,WAAW,IAAA,EAAM;AACvD,IAAA,OAAA,GAAW,IAAA,CAA2B,KAAA;AAAA,EACxC,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,QAAQ,MAAM,CAAA,CAAA;AAAA,EAC1B;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAqB,MAAM,CAAA;AAC9C,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO,IAAI,WAAW,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AAAA,EACnE;AACA,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,OAAO,IAAI,oBAAoB,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AAAA,EAC5E;AACA,EAAA,OAAO,IAAI,eAAe,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAQ,EAAG,MAAM,OAAO,CAAA;AACvE","file":"chunk-VYGIWHRU.js","sourcesContent":["/**\n * 서버가 에러 응답의 `code` 로 싣는 값.\n *\n * 문구가 아니라 **이 값으로 분기한다** — 한글 메시지는 바뀔 수 있다.\n *\n * ⚠️ 문자 도메인은 snake_case, 카카오 채널 도메인은 SCREAMING_CASE 다. 서버가 실제로\n * 그렇게 보내므로 SDK 가 임의로 정규화하지 않는다. 열린 유니온이라 목록에 없는 코드도\n * 그대로 실린다(자동완성만 돕는다).\n */\nexport type ClawOpsErrorCode =\n // 발송 일반\n | 'invalid_phone'\n | 'invalid_type'\n | 'invalid_input'\n | 'from_not_registered'\n | 'body_too_long'\n | 'sms_no_subject'\n | 'sms_no_media'\n | 'lms_no_media'\n | 'too_many_media'\n | 'invalid_media_ext'\n | 'media_download_failed'\n | 'type_not_supported'\n | 'messaging_blocked'\n | 'recipient_blocked'\n | 'quota_exceeded'\n | 'override_quota_exceeded'\n | 'no_active_subscription'\n // 알림톡 발송\n | 'kakao_required'\n | 'kakao_type_conflict'\n | 'kakao_body_not_allowed'\n | 'kakao_subject_not_allowed'\n | 'kakao_media_not_allowed'\n | 'kakao_channel_not_found'\n | 'kakao_template_not_found'\n | 'kakao_template_not_approved'\n | 'kakao_template_dormant'\n | 'kakao_variable_missing'\n | 'kakao_variable_unknown'\n | 'kakao_send_failed'\n | 'kakao_unavailable'\n | 'invalid_fallback_type'\n // 카카오 채널 연동\n | 'KAKAO_TOKEN_INVALID'\n | 'KAKAO_CHANNEL_ALREADY_LINKED'\n | 'KAKAO_CHANNEL_REJECTED'\n | 'KAKAO_RATE_LIMITED'\n | 'KAKAO_PROVIDER_UNAVAILABLE'\n // 공통\n | 'VALIDATION'\n | 'NOT_FOUND'\n | (string & {});\n\nexport class ClawOpsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ClawOpsError';\n }\n}\n\nexport class APIError extends ClawOpsError {\n readonly request: { method: string; url: string };\n\n constructor(message: string, request: { method: string; url: string }) {\n super(message);\n this.name = 'APIError';\n this.request = request;\n }\n}\n\nexport class APIStatusError extends APIError {\n readonly status: number;\n readonly body: unknown;\n readonly headers: Headers | undefined;\n /**\n * 서버가 함께 보낸 기계 판독용 코드(`{ error, code }`). 없으면 undefined 다.\n *\n * 같은 상태 코드가 서로 다른 사유를 담는다 — 422 만 해도 수신거부(`recipient_blocked`)와\n * 할당량 초과(`quota_exceeded`)가 갈리고, 한글 문구로 구분하면 문구가 바뀔 때 깨진다.\n */\n readonly code: ClawOpsErrorCode | undefined;\n\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, request);\n this.name = 'APIStatusError';\n this.status = response.status;\n this.body = body;\n this.headers = response.headers;\n this.code = extractErrorCode(body);\n }\n}\n\n/** 응답 본문에서 `code` 를 꺼낸다. 문자열이 아니면 없는 것으로 본다. */\nfunction extractErrorCode(body: unknown): ClawOpsErrorCode | undefined {\n const code = (body as { code?: unknown } | null | undefined)?.code;\n return typeof code === 'string' && code !== '' ? code : undefined;\n}\n\nexport class BadRequestError extends APIStatusError {\n override readonly status = 400 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends APIStatusError {\n override readonly status = 401 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class PermissionDeniedError extends APIStatusError {\n override readonly status = 403 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'PermissionDeniedError';\n }\n}\n\nexport class NotFoundError extends APIStatusError {\n override readonly status = 404 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends APIStatusError {\n override readonly status = 409 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'ConflictError';\n }\n}\n\nexport class UnprocessableEntityError extends APIStatusError {\n override readonly status = 422 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * HTTP 429 Too Many Requests.\n *\n * 동시 통화 한도 초과 등 일시적 제한. SDK는 자동 재시도(최대 2회, 지수 backoff)를 수행한다.\n * 즉각 피드백이 필요하면 client 생성 시 maxRetries: 0으로 재시도를 비활성화하라.\n */\nexport class RateLimitError extends APIStatusError {\n override readonly status = 429 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'RateLimitError';\n }\n}\n\nexport class InternalServerError extends APIStatusError {\n override readonly status = 500 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'InternalServerError';\n }\n}\n\nexport class ServiceUnavailableError extends APIStatusError {\n override readonly status = 503 as const;\n constructor(\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) {\n super(message, response, body, request);\n this.name = 'ServiceUnavailableError';\n }\n}\n\nexport class APIConnectionError extends APIError {\n constructor(request: { method: string; url: string }, message = 'Connection error.') {\n super(message, request);\n this.name = 'APIConnectionError';\n }\n}\n\nexport class APITimeoutError extends APIConnectionError {\n constructor(request: { method: string; url: string }) {\n super(request, 'Request timed out.');\n this.name = 'APITimeoutError';\n }\n}\n\nexport class APIResponseValidationError extends APIError {\n readonly status: number;\n\n constructor(response: { status: number }, request: { method: string; url: string }) {\n super('API response validation failed.', request);\n this.name = 'APIResponseValidationError';\n this.status = response.status;\n }\n}\n\n/**\n * 솔라피 호환 레이어가 호출을 거절할 때 쓴다.\n * 조용히 다르게 동작하느니 여기서 멈추는 편이 낫다고 판단한 경우들이다.\n */\nexport class SolapiBridgeError extends ClawOpsError {\n constructor(message: string) {\n super(message);\n this.name = 'SolapiBridgeError';\n }\n}\n\nexport class AgentError extends ClawOpsError {\n constructor(message: string) {\n super(message);\n this.name = 'AgentError';\n }\n}\n\nexport class AgentConnectionError extends AgentError {\n constructor(message = 'Agent WebSocket connection failed.') {\n super(message);\n this.name = 'AgentConnectionError';\n }\n}\n\nconst STATUS_CODE_TO_ERROR: Record<\n number,\n new (\n message: string,\n response: { status: number; headers?: Headers },\n body: unknown,\n request: { method: string; url: string },\n ) => APIStatusError\n> = {\n 400: BadRequestError,\n 401: AuthenticationError,\n 403: PermissionDeniedError,\n 404: NotFoundError,\n 409: ConflictError,\n 422: UnprocessableEntityError,\n 429: RateLimitError,\n 500: InternalServerError,\n 503: ServiceUnavailableError,\n};\n\nexport function makeStatusError(\n status: number,\n body: unknown,\n headers: Headers | undefined,\n request: { method: string; url: string },\n): APIStatusError {\n let message = '';\n if (body && typeof body === 'object' && 'error' in body) {\n message = (body as { error: string }).error;\n } else {\n message = `HTTP ${status}`;\n }\n\n const ErrorClass = STATUS_CODE_TO_ERROR[status];\n if (ErrorClass) {\n return new ErrorClass(message, { status, headers }, body, request);\n }\n if (status >= 500) {\n return new InternalServerError(message, { status, headers }, body, request);\n }\n return new APIStatusError(message, { status, headers }, body, request);\n}\n"]}
|