@kadoa/mcp 0.3.9-rc.1 → 0.3.9-rc.2
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/index.js +367 -158
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -28820,6 +28820,17 @@ function isArrayBufferView(val) {
|
|
|
28820
28820
|
}
|
|
28821
28821
|
return result;
|
|
28822
28822
|
}
|
|
28823
|
+
function getGlobal() {
|
|
28824
|
+
if (typeof globalThis !== "undefined")
|
|
28825
|
+
return globalThis;
|
|
28826
|
+
if (typeof self !== "undefined")
|
|
28827
|
+
return self;
|
|
28828
|
+
if (typeof window !== "undefined")
|
|
28829
|
+
return window;
|
|
28830
|
+
if (typeof global !== "undefined")
|
|
28831
|
+
return global;
|
|
28832
|
+
return {};
|
|
28833
|
+
}
|
|
28823
28834
|
function forEach(obj, fn, { allOwnKeys = false } = {}) {
|
|
28824
28835
|
if (obj === null || typeof obj === "undefined") {
|
|
28825
28836
|
return;
|
|
@@ -28906,10 +28917,14 @@ var toString, getPrototypeOf, iterator, toStringTag, kindOf, kindOfTest = (type)
|
|
|
28906
28917
|
} catch (e) {
|
|
28907
28918
|
return false;
|
|
28908
28919
|
}
|
|
28909
|
-
}, isDate, isFile,
|
|
28920
|
+
}, isDate, isFile, isReactNativeBlob = (value) => {
|
|
28921
|
+
return !!(value && typeof value.uri !== "undefined");
|
|
28922
|
+
}, isReactNative = (formData) => formData && typeof formData.getParts !== "undefined", isBlob, isFileList, isStream = (val) => isObject2(val) && isFunction(val.pipe), G, FormDataCtor, isFormData = (thing) => {
|
|
28910
28923
|
let kind;
|
|
28911
|
-
return thing && (
|
|
28912
|
-
}, isURLSearchParams, isReadableStream, isRequest, isResponse, isHeaders, trim = (str) =>
|
|
28924
|
+
return thing && (FormDataCtor && thing instanceof FormDataCtor || isFunction(thing.append) && ((kind = kindOf(thing)) === "formdata" || kind === "object" && isFunction(thing.toString) && thing.toString() === "[object FormData]"));
|
|
28925
|
+
}, isURLSearchParams, isReadableStream, isRequest, isResponse, isHeaders, trim = (str) => {
|
|
28926
|
+
return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
|
|
28927
|
+
}, _global, isContextDefined = (context) => !isUndefined(context) && context !== _global, extend2 = (a, b, thisArg, { allOwnKeys } = {}) => {
|
|
28913
28928
|
forEach(b, (val, key) => {
|
|
28914
28929
|
if (thisArg && isFunction(val)) {
|
|
28915
28930
|
Object.defineProperty(a, key, {
|
|
@@ -29089,6 +29104,8 @@ var init_utils = __esm(() => {
|
|
|
29089
29104
|
isFile = kindOfTest("File");
|
|
29090
29105
|
isBlob = kindOfTest("Blob");
|
|
29091
29106
|
isFileList = kindOfTest("FileList");
|
|
29107
|
+
G = getGlobal();
|
|
29108
|
+
FormDataCtor = typeof G.FormData !== "undefined" ? G.FormData : undefined;
|
|
29092
29109
|
isURLSearchParams = kindOfTest("URLSearchParams");
|
|
29093
29110
|
[isReadableStream, isRequest, isResponse, isHeaders] = [
|
|
29094
29111
|
"ReadableStream",
|
|
@@ -29146,6 +29163,8 @@ var init_utils = __esm(() => {
|
|
|
29146
29163
|
isUndefined,
|
|
29147
29164
|
isDate,
|
|
29148
29165
|
isFile,
|
|
29166
|
+
isReactNativeBlob,
|
|
29167
|
+
isReactNative,
|
|
29149
29168
|
isBlob,
|
|
29150
29169
|
isRegExp,
|
|
29151
29170
|
isFunction,
|
|
@@ -29197,11 +29216,20 @@ var init_AxiosError = __esm(() => {
|
|
|
29197
29216
|
const axiosError = new AxiosError(error48.message, code || error48.code, config2, request, response);
|
|
29198
29217
|
axiosError.cause = error48;
|
|
29199
29218
|
axiosError.name = error48.name;
|
|
29219
|
+
if (error48.status != null && axiosError.status == null) {
|
|
29220
|
+
axiosError.status = error48.status;
|
|
29221
|
+
}
|
|
29200
29222
|
customProps && Object.assign(axiosError, customProps);
|
|
29201
29223
|
return axiosError;
|
|
29202
29224
|
}
|
|
29203
29225
|
constructor(message, code, config2, request, response) {
|
|
29204
29226
|
super(message);
|
|
29227
|
+
Object.defineProperty(this, "message", {
|
|
29228
|
+
value: message,
|
|
29229
|
+
enumerable: true,
|
|
29230
|
+
writable: true,
|
|
29231
|
+
configurable: true
|
|
29232
|
+
});
|
|
29205
29233
|
this.name = "AxiosError";
|
|
29206
29234
|
this.isAxiosError = true;
|
|
29207
29235
|
code && (this.code = code);
|
|
@@ -39414,6 +39442,10 @@ function toFormData(obj, formData, options) {
|
|
|
39414
39442
|
}
|
|
39415
39443
|
function defaultVisitor(value, key, path) {
|
|
39416
39444
|
let arr = value;
|
|
39445
|
+
if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) {
|
|
39446
|
+
formData.append(renderKey(path, key, dots), convertValue(value));
|
|
39447
|
+
return false;
|
|
39448
|
+
}
|
|
39417
39449
|
if (value && !path && typeof value === "object") {
|
|
39418
39450
|
if (utils_default.endsWith(key, "{}")) {
|
|
39419
39451
|
key = metaTokens ? key : key.slice(0, -2);
|
|
@@ -39763,66 +39795,70 @@ var init_defaults = __esm(() => {
|
|
|
39763
39795
|
defaults = {
|
|
39764
39796
|
transitional: transitional_default,
|
|
39765
39797
|
adapter: ["xhr", "http", "fetch"],
|
|
39766
|
-
transformRequest: [
|
|
39767
|
-
|
|
39768
|
-
|
|
39769
|
-
|
|
39770
|
-
|
|
39771
|
-
|
|
39772
|
-
|
|
39773
|
-
|
|
39774
|
-
|
|
39775
|
-
|
|
39776
|
-
|
|
39777
|
-
|
|
39778
|
-
|
|
39779
|
-
|
|
39780
|
-
|
|
39781
|
-
|
|
39782
|
-
|
|
39783
|
-
|
|
39784
|
-
|
|
39785
|
-
|
|
39786
|
-
|
|
39787
|
-
|
|
39788
|
-
|
|
39789
|
-
if (
|
|
39790
|
-
|
|
39798
|
+
transformRequest: [
|
|
39799
|
+
function transformRequest(data, headers) {
|
|
39800
|
+
const contentType = headers.getContentType() || "";
|
|
39801
|
+
const hasJSONContentType = contentType.indexOf("application/json") > -1;
|
|
39802
|
+
const isObjectPayload = utils_default.isObject(data);
|
|
39803
|
+
if (isObjectPayload && utils_default.isHTMLForm(data)) {
|
|
39804
|
+
data = new FormData(data);
|
|
39805
|
+
}
|
|
39806
|
+
const isFormData2 = utils_default.isFormData(data);
|
|
39807
|
+
if (isFormData2) {
|
|
39808
|
+
return hasJSONContentType ? JSON.stringify(formDataToJSON_default(data)) : data;
|
|
39809
|
+
}
|
|
39810
|
+
if (utils_default.isArrayBuffer(data) || utils_default.isBuffer(data) || utils_default.isStream(data) || utils_default.isFile(data) || utils_default.isBlob(data) || utils_default.isReadableStream(data)) {
|
|
39811
|
+
return data;
|
|
39812
|
+
}
|
|
39813
|
+
if (utils_default.isArrayBufferView(data)) {
|
|
39814
|
+
return data.buffer;
|
|
39815
|
+
}
|
|
39816
|
+
if (utils_default.isURLSearchParams(data)) {
|
|
39817
|
+
headers.setContentType("application/x-www-form-urlencoded;charset=utf-8", false);
|
|
39818
|
+
return data.toString();
|
|
39819
|
+
}
|
|
39820
|
+
let isFileList2;
|
|
39821
|
+
if (isObjectPayload) {
|
|
39822
|
+
if (contentType.indexOf("application/x-www-form-urlencoded") > -1) {
|
|
39823
|
+
return toURLEncodedForm(data, this.formSerializer).toString();
|
|
39824
|
+
}
|
|
39825
|
+
if ((isFileList2 = utils_default.isFileList(data)) || contentType.indexOf("multipart/form-data") > -1) {
|
|
39826
|
+
const _FormData = this.env && this.env.FormData;
|
|
39827
|
+
return toFormData_default(isFileList2 ? { "files[]": data } : data, _FormData && new _FormData, this.formSerializer);
|
|
39828
|
+
}
|
|
39791
39829
|
}
|
|
39792
|
-
if (
|
|
39793
|
-
|
|
39794
|
-
return
|
|
39830
|
+
if (isObjectPayload || hasJSONContentType) {
|
|
39831
|
+
headers.setContentType("application/json", false);
|
|
39832
|
+
return stringifySafely(data);
|
|
39795
39833
|
}
|
|
39796
|
-
}
|
|
39797
|
-
if (isObjectPayload || hasJSONContentType) {
|
|
39798
|
-
headers.setContentType("application/json", false);
|
|
39799
|
-
return stringifySafely(data);
|
|
39800
|
-
}
|
|
39801
|
-
return data;
|
|
39802
|
-
}],
|
|
39803
|
-
transformResponse: [function transformResponse(data) {
|
|
39804
|
-
const transitional = this.transitional || defaults.transitional;
|
|
39805
|
-
const forcedJSONParsing = transitional && transitional.forcedJSONParsing;
|
|
39806
|
-
const JSONRequested = this.responseType === "json";
|
|
39807
|
-
if (utils_default.isResponse(data) || utils_default.isReadableStream(data)) {
|
|
39808
39834
|
return data;
|
|
39809
39835
|
}
|
|
39810
|
-
|
|
39811
|
-
|
|
39812
|
-
|
|
39813
|
-
|
|
39814
|
-
|
|
39815
|
-
|
|
39816
|
-
|
|
39817
|
-
|
|
39818
|
-
|
|
39836
|
+
],
|
|
39837
|
+
transformResponse: [
|
|
39838
|
+
function transformResponse(data) {
|
|
39839
|
+
const transitional = this.transitional || defaults.transitional;
|
|
39840
|
+
const forcedJSONParsing = transitional && transitional.forcedJSONParsing;
|
|
39841
|
+
const JSONRequested = this.responseType === "json";
|
|
39842
|
+
if (utils_default.isResponse(data) || utils_default.isReadableStream(data)) {
|
|
39843
|
+
return data;
|
|
39844
|
+
}
|
|
39845
|
+
if (data && utils_default.isString(data) && (forcedJSONParsing && !this.responseType || JSONRequested)) {
|
|
39846
|
+
const silentJSONParsing = transitional && transitional.silentJSONParsing;
|
|
39847
|
+
const strictJSONParsing = !silentJSONParsing && JSONRequested;
|
|
39848
|
+
try {
|
|
39849
|
+
return JSON.parse(data, this.parseReviver);
|
|
39850
|
+
} catch (e) {
|
|
39851
|
+
if (strictJSONParsing) {
|
|
39852
|
+
if (e.name === "SyntaxError") {
|
|
39853
|
+
throw AxiosError_default.from(e, AxiosError_default.ERR_BAD_RESPONSE, this, null, this.response);
|
|
39854
|
+
}
|
|
39855
|
+
throw e;
|
|
39819
39856
|
}
|
|
39820
|
-
throw e;
|
|
39821
39857
|
}
|
|
39822
39858
|
}
|
|
39859
|
+
return data;
|
|
39823
39860
|
}
|
|
39824
|
-
|
|
39825
|
-
}],
|
|
39861
|
+
],
|
|
39826
39862
|
timeout: 0,
|
|
39827
39863
|
xsrfCookieName: "XSRF-TOKEN",
|
|
39828
39864
|
xsrfHeaderName: "X-XSRF-TOKEN",
|
|
@@ -40118,7 +40154,14 @@ var init_AxiosHeaders = __esm(() => {
|
|
|
40118
40154
|
return this;
|
|
40119
40155
|
}
|
|
40120
40156
|
};
|
|
40121
|
-
AxiosHeaders.accessor([
|
|
40157
|
+
AxiosHeaders.accessor([
|
|
40158
|
+
"Content-Type",
|
|
40159
|
+
"Content-Length",
|
|
40160
|
+
"Accept",
|
|
40161
|
+
"Accept-Encoding",
|
|
40162
|
+
"User-Agent",
|
|
40163
|
+
"Authorization"
|
|
40164
|
+
]);
|
|
40122
40165
|
utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => {
|
|
40123
40166
|
let mapped = key[0].toUpperCase() + key.slice(1);
|
|
40124
40167
|
return {
|
|
@@ -41381,7 +41424,7 @@ var require_follow_redirects = __commonJS((exports, module) => {
|
|
|
41381
41424
|
});
|
|
41382
41425
|
|
|
41383
41426
|
// node_modules/axios/lib/env/data.js
|
|
41384
|
-
var VERSION = "1.13.
|
|
41427
|
+
var VERSION = "1.13.6";
|
|
41385
41428
|
|
|
41386
41429
|
// node_modules/axios/lib/helpers/parseProtocol.js
|
|
41387
41430
|
function parseProtocol(url3) {
|
|
@@ -41791,11 +41834,14 @@ var progressEventReducer = (listener, isDownloadStream, freq = 3) => {
|
|
|
41791
41834
|
}, freq);
|
|
41792
41835
|
}, progressEventDecorator = (total, throttled) => {
|
|
41793
41836
|
const lengthComputable = total != null;
|
|
41794
|
-
return [
|
|
41795
|
-
|
|
41796
|
-
|
|
41797
|
-
|
|
41798
|
-
|
|
41837
|
+
return [
|
|
41838
|
+
(loaded) => throttled[0]({
|
|
41839
|
+
lengthComputable,
|
|
41840
|
+
total,
|
|
41841
|
+
loaded
|
|
41842
|
+
}),
|
|
41843
|
+
throttled[1]
|
|
41844
|
+
];
|
|
41799
41845
|
}, asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args));
|
|
41800
41846
|
var init_progressEventReducer = __esm(() => {
|
|
41801
41847
|
init_speedometer();
|
|
@@ -41925,10 +41971,7 @@ class Http2Sessions {
|
|
|
41925
41971
|
};
|
|
41926
41972
|
}
|
|
41927
41973
|
session.once("close", removeSession);
|
|
41928
|
-
let entry = [
|
|
41929
|
-
session,
|
|
41930
|
-
options
|
|
41931
|
-
];
|
|
41974
|
+
let entry = [session, options];
|
|
41932
41975
|
authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry];
|
|
41933
41976
|
return session;
|
|
41934
41977
|
}
|
|
@@ -42049,12 +42092,7 @@ var init_http = __esm(() => {
|
|
|
42049
42092
|
const authority = options.protocol + "//" + options.hostname + ":" + (options.port || (options.protocol === "https:" ? 443 : 80));
|
|
42050
42093
|
const { http2Options, headers } = options;
|
|
42051
42094
|
const session = http2Sessions.getSession(authority, http2Options);
|
|
42052
|
-
const {
|
|
42053
|
-
HTTP2_HEADER_SCHEME,
|
|
42054
|
-
HTTP2_HEADER_METHOD,
|
|
42055
|
-
HTTP2_HEADER_PATH,
|
|
42056
|
-
HTTP2_HEADER_STATUS
|
|
42057
|
-
} = http2.constants;
|
|
42095
|
+
const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = http2.constants;
|
|
42058
42096
|
const http2Headers = {
|
|
42059
42097
|
[HTTP2_HEADER_SCHEME]: options.protocol.replace(":", ""),
|
|
42060
42098
|
[HTTP2_HEADER_METHOD]: options.method,
|
|
@@ -42241,9 +42279,12 @@ var init_http = __esm(() => {
|
|
|
42241
42279
|
if (!utils_default.isStream(data)) {
|
|
42242
42280
|
data = stream3.Readable.from(data, { objectMode: false });
|
|
42243
42281
|
}
|
|
42244
|
-
data = stream3.pipeline([
|
|
42245
|
-
|
|
42246
|
-
|
|
42282
|
+
data = stream3.pipeline([
|
|
42283
|
+
data,
|
|
42284
|
+
new AxiosTransformStream_default({
|
|
42285
|
+
maxRate: utils_default.toFiniteNumber(maxUploadRate)
|
|
42286
|
+
})
|
|
42287
|
+
], utils_default.noop);
|
|
42247
42288
|
onUploadProgress && data.on("progress", flushOnFinish(data, progressEventDecorator(contentLength, progressEventReducer(asyncDecorator(onUploadProgress), false, 3))));
|
|
42248
42289
|
}
|
|
42249
42290
|
let auth = undefined;
|
|
@@ -43073,11 +43114,7 @@ var DEFAULT_CHUNK_SIZE, isFunction2, globalFetchAPI, ReadableStream2, TextEncode
|
|
|
43073
43114
|
}, seedCache, getFetch = (config2) => {
|
|
43074
43115
|
let env = config2 && config2.env || {};
|
|
43075
43116
|
const { fetch: fetch2, Request, Response: Response2 } = env;
|
|
43076
|
-
const seeds = [
|
|
43077
|
-
Request,
|
|
43078
|
-
Response2,
|
|
43079
|
-
fetch2
|
|
43080
|
-
];
|
|
43117
|
+
const seeds = [Request, Response2, fetch2];
|
|
43081
43118
|
let len = seeds.length, i = len, seed, target, map3 = seedCache;
|
|
43082
43119
|
while (i--) {
|
|
43083
43120
|
seed = seeds[i];
|
|
@@ -43102,10 +43139,7 @@ var init_fetch = __esm(() => {
|
|
|
43102
43139
|
Request,
|
|
43103
43140
|
Response: Response2
|
|
43104
43141
|
}))(utils_default.global);
|
|
43105
|
-
({
|
|
43106
|
-
ReadableStream: ReadableStream2,
|
|
43107
|
-
TextEncoder: TextEncoder2
|
|
43108
|
-
} = utils_default.global);
|
|
43142
|
+
({ ReadableStream: ReadableStream2, TextEncoder: TextEncoder2 } = utils_default.global);
|
|
43109
43143
|
seedCache = new Map;
|
|
43110
43144
|
adapter = getFetch();
|
|
43111
43145
|
});
|
|
@@ -47552,7 +47586,7 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
|
|
|
47552
47586
|
const newSettings = await Promise.all(eventTypes.map(async (eventType) => {
|
|
47553
47587
|
const existing = existingSettings.find((s) => s.eventType === eventType);
|
|
47554
47588
|
if (existing?.id) {
|
|
47555
|
-
const existingChannelIds = (existing.channels || []).map((
|
|
47589
|
+
const existingChannelIds = (existing.channels || []).map((channel) => channel.id).filter(Boolean);
|
|
47556
47590
|
const mergedChannelIds = [
|
|
47557
47591
|
.../* @__PURE__ */ new Set([...existingChannelIds, ...channelIds])
|
|
47558
47592
|
];
|
|
@@ -47678,87 +47712,246 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
|
|
|
47678
47712
|
}));
|
|
47679
47713
|
return channels;
|
|
47680
47714
|
}
|
|
47681
|
-
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.
|
|
47715
|
+
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.24.2", SDK_NAME = "kadoa-node-sdk", SDK_LANGUAGE = "node", debug5, isDrainControlMessage = (message) => message.type === "control.draining", isRealtimeEvent = (message) => message.type !== "heartbeat" && message.type !== "control.draining", _Realtime = class _Realtime2 {
|
|
47682
47716
|
constructor(config2) {
|
|
47717
|
+
this.drainingSockets = /* @__PURE__ */ new Set;
|
|
47683
47718
|
this.lastHeartbeat = Date.now();
|
|
47684
47719
|
this.isConnecting = false;
|
|
47685
47720
|
this.eventListeners = /* @__PURE__ */ new Set;
|
|
47686
47721
|
this.connectionListeners = /* @__PURE__ */ new Set;
|
|
47687
47722
|
this.errorListeners = /* @__PURE__ */ new Set;
|
|
47723
|
+
this.isClosed = false;
|
|
47724
|
+
this.hasConnectedOnce = false;
|
|
47725
|
+
this.recentEventIds = /* @__PURE__ */ new Set;
|
|
47726
|
+
this.recentEventIdQueue = [];
|
|
47727
|
+
this.maxRecentEventIds = 1000;
|
|
47688
47728
|
this.apiKey = config2.apiKey;
|
|
47689
47729
|
this.heartbeatInterval = config2.heartbeatInterval || 1e4;
|
|
47690
|
-
this.reconnectDelay = config2.reconnectDelay
|
|
47730
|
+
this.reconnectDelay = this.normalizeReconnectDelay(config2.reconnectDelay);
|
|
47691
47731
|
this.missedHeartbeatsLimit = config2.missedHeartbeatsLimit || 30000;
|
|
47692
47732
|
}
|
|
47693
47733
|
async connect() {
|
|
47694
|
-
if (this.isConnecting)
|
|
47734
|
+
if (this.isClosed || this.isConnecting || this.activeSocket) {
|
|
47695
47735
|
return;
|
|
47736
|
+
}
|
|
47696
47737
|
this.isConnecting = true;
|
|
47697
47738
|
try {
|
|
47698
|
-
const
|
|
47699
|
-
|
|
47700
|
-
|
|
47701
|
-
"Content-Type": "application/json",
|
|
47702
|
-
"x-api-key": `${this.apiKey}`,
|
|
47703
|
-
"x-sdk-version": SDK_VERSION
|
|
47704
|
-
}
|
|
47705
|
-
});
|
|
47706
|
-
const { access_token, team_id } = await response.json();
|
|
47707
|
-
await new Promise((resolve, reject) => {
|
|
47708
|
-
this.socket = new WebSocket(`${WSS_API_URI}?access_token=${access_token}`);
|
|
47709
|
-
this.socket.onopen = () => {
|
|
47710
|
-
this.isConnecting = false;
|
|
47711
|
-
this.lastHeartbeat = Date.now();
|
|
47712
|
-
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
47713
|
-
this.socket.send(JSON.stringify({
|
|
47714
|
-
action: "subscribe",
|
|
47715
|
-
channel: team_id
|
|
47716
|
-
}));
|
|
47717
|
-
debug5("Connected to WebSocket");
|
|
47718
|
-
this.notifyConnectionListeners(true);
|
|
47719
|
-
}
|
|
47720
|
-
this.startHeartbeatCheck();
|
|
47721
|
-
resolve();
|
|
47722
|
-
};
|
|
47723
|
-
this.socket.onmessage = (event) => {
|
|
47724
|
-
try {
|
|
47725
|
-
const data = JSON.parse(event.data);
|
|
47726
|
-
if (data.type === "heartbeat") {
|
|
47727
|
-
this.handleHeartbeat();
|
|
47728
|
-
} else {
|
|
47729
|
-
if (data?.id) {
|
|
47730
|
-
fetch(`${REALTIME_API_URI}/api/v1/events/ack`, {
|
|
47731
|
-
method: "POST",
|
|
47732
|
-
headers: { "Content-Type": "application/json" },
|
|
47733
|
-
body: JSON.stringify({ id: data.id })
|
|
47734
|
-
});
|
|
47735
|
-
}
|
|
47736
|
-
this.notifyEventListeners(data);
|
|
47737
|
-
}
|
|
47738
|
-
} catch (err) {
|
|
47739
|
-
debug5("Failed to parse incoming message: %O", err);
|
|
47740
|
-
}
|
|
47741
|
-
};
|
|
47742
|
-
this.socket.onclose = () => {
|
|
47743
|
-
debug5("WebSocket disconnected. Attempting to reconnect...");
|
|
47744
|
-
this.isConnecting = false;
|
|
47745
|
-
this.stopHeartbeatCheck();
|
|
47746
|
-
this.notifyConnectionListeners(false, "Connection closed");
|
|
47747
|
-
setTimeout(() => this.connect(), this.reconnectDelay);
|
|
47748
|
-
};
|
|
47749
|
-
this.socket.onerror = (error48) => {
|
|
47750
|
-
debug5("WebSocket error: %O", error48);
|
|
47751
|
-
this.isConnecting = false;
|
|
47752
|
-
this.notifyErrorListeners(error48);
|
|
47753
|
-
reject(error48);
|
|
47754
|
-
};
|
|
47755
|
-
});
|
|
47739
|
+
const { access_token, team_id } = await this.getOAuthToken();
|
|
47740
|
+
await this.openSocket(access_token, team_id, "active");
|
|
47741
|
+
this.hasConnectedOnce = true;
|
|
47756
47742
|
} catch (err) {
|
|
47757
47743
|
debug5("Failed to connect: %O", err);
|
|
47758
47744
|
this.isConnecting = false;
|
|
47759
|
-
|
|
47745
|
+
this.notifyErrorListeners(err);
|
|
47746
|
+
if (!this.hasConnectedOnce) {
|
|
47747
|
+
throw err;
|
|
47748
|
+
}
|
|
47749
|
+
this.scheduleReconnect();
|
|
47760
47750
|
}
|
|
47761
47751
|
}
|
|
47752
|
+
async getOAuthToken() {
|
|
47753
|
+
const response = await fetch(`${PUBLIC_API_URI}/v4/oauth2/token`, {
|
|
47754
|
+
method: "POST",
|
|
47755
|
+
headers: {
|
|
47756
|
+
"Content-Type": "application/json",
|
|
47757
|
+
"x-api-key": `${this.apiKey}`,
|
|
47758
|
+
"x-sdk-version": SDK_VERSION
|
|
47759
|
+
}
|
|
47760
|
+
});
|
|
47761
|
+
return await response.json();
|
|
47762
|
+
}
|
|
47763
|
+
async openSocket(accessToken, teamId, role) {
|
|
47764
|
+
await new Promise((resolve, reject) => {
|
|
47765
|
+
const socket = new WebSocket(`${WSS_API_URI}?access_token=${accessToken}`);
|
|
47766
|
+
let settled = false;
|
|
47767
|
+
socket.onopen = () => {
|
|
47768
|
+
const subscribeMessage = {
|
|
47769
|
+
action: "subscribe",
|
|
47770
|
+
channel: teamId
|
|
47771
|
+
};
|
|
47772
|
+
if (this.lastCursor) {
|
|
47773
|
+
subscribeMessage.lastCursor = this.lastCursor;
|
|
47774
|
+
}
|
|
47775
|
+
socket.send(JSON.stringify(subscribeMessage));
|
|
47776
|
+
this.promoteSocket(socket, role);
|
|
47777
|
+
this.isConnecting = false;
|
|
47778
|
+
this.lastHeartbeat = Date.now();
|
|
47779
|
+
this.startHeartbeatCheck();
|
|
47780
|
+
debug5("Connected to WebSocket");
|
|
47781
|
+
if (!settled) {
|
|
47782
|
+
settled = true;
|
|
47783
|
+
resolve();
|
|
47784
|
+
}
|
|
47785
|
+
};
|
|
47786
|
+
socket.onmessage = (event) => {
|
|
47787
|
+
this.handleSocketMessage(socket, event.data);
|
|
47788
|
+
};
|
|
47789
|
+
socket.onclose = () => {
|
|
47790
|
+
this.handleSocketClose(socket);
|
|
47791
|
+
if (!settled) {
|
|
47792
|
+
settled = true;
|
|
47793
|
+
reject(new Error("WebSocket closed before opening"));
|
|
47794
|
+
}
|
|
47795
|
+
};
|
|
47796
|
+
socket.onerror = (error48) => {
|
|
47797
|
+
this.notifyErrorListeners(error48);
|
|
47798
|
+
if (!settled) {
|
|
47799
|
+
settled = true;
|
|
47800
|
+
reject(error48);
|
|
47801
|
+
return;
|
|
47802
|
+
}
|
|
47803
|
+
if (socket === this.activeSocket) {
|
|
47804
|
+
this.handleUnexpectedDisconnect("Socket error");
|
|
47805
|
+
}
|
|
47806
|
+
};
|
|
47807
|
+
});
|
|
47808
|
+
}
|
|
47809
|
+
promoteSocket(socket, role) {
|
|
47810
|
+
if (role === "replacement" && this.activeSocket && this.activeSocket !== socket) {
|
|
47811
|
+
this.drainingSockets.add(this.activeSocket);
|
|
47812
|
+
}
|
|
47813
|
+
this.activeSocket = socket;
|
|
47814
|
+
this.drainingSockets.delete(socket);
|
|
47815
|
+
if (role === "active" || !this.hasConnectedOnce) {
|
|
47816
|
+
this.notifyConnectionListeners(true);
|
|
47817
|
+
}
|
|
47818
|
+
}
|
|
47819
|
+
handleSocketMessage(socket, rawData) {
|
|
47820
|
+
try {
|
|
47821
|
+
const payload = typeof rawData === "string" ? rawData : rawData.toString?.() ?? "";
|
|
47822
|
+
const data = JSON.parse(payload);
|
|
47823
|
+
if (data.type === "heartbeat") {
|
|
47824
|
+
if (socket === this.activeSocket) {
|
|
47825
|
+
this.handleHeartbeat();
|
|
47826
|
+
}
|
|
47827
|
+
return;
|
|
47828
|
+
}
|
|
47829
|
+
if (isDrainControlMessage(data)) {
|
|
47830
|
+
this.handleDrainSignal(socket, data);
|
|
47831
|
+
return;
|
|
47832
|
+
}
|
|
47833
|
+
if (!isRealtimeEvent(data)) {
|
|
47834
|
+
return;
|
|
47835
|
+
}
|
|
47836
|
+
if (typeof data._cursor === "string") {
|
|
47837
|
+
this.lastCursor = data._cursor;
|
|
47838
|
+
}
|
|
47839
|
+
if (typeof data.id === "string") {
|
|
47840
|
+
fetch(`${REALTIME_API_URI}/api/v1/events/ack`, {
|
|
47841
|
+
method: "POST",
|
|
47842
|
+
headers: { "Content-Type": "application/json" },
|
|
47843
|
+
body: JSON.stringify({ id: data.id })
|
|
47844
|
+
}).catch((error48) => {
|
|
47845
|
+
debug5("Failed to acknowledge event %s: %O", data.id, error48);
|
|
47846
|
+
});
|
|
47847
|
+
}
|
|
47848
|
+
if (this.isDuplicateEvent(data.id)) {
|
|
47849
|
+
return;
|
|
47850
|
+
}
|
|
47851
|
+
this.notifyEventListeners(data);
|
|
47852
|
+
} catch (err) {
|
|
47853
|
+
debug5("Failed to parse incoming message: %O", err);
|
|
47854
|
+
}
|
|
47855
|
+
}
|
|
47856
|
+
handleDrainSignal(socket, message) {
|
|
47857
|
+
if (socket !== this.activeSocket || this.isClosed) {
|
|
47858
|
+
return;
|
|
47859
|
+
}
|
|
47860
|
+
debug5("Received drain signal, preparing replacement socket");
|
|
47861
|
+
this.drainingSockets.add(socket);
|
|
47862
|
+
this.scheduleDrainReconnect(message.retryAfterMs);
|
|
47863
|
+
}
|
|
47864
|
+
handleSocketClose(socket) {
|
|
47865
|
+
const wasActiveSocket = socket === this.activeSocket;
|
|
47866
|
+
this.drainingSockets.delete(socket);
|
|
47867
|
+
if (!wasActiveSocket) {
|
|
47868
|
+
return;
|
|
47869
|
+
}
|
|
47870
|
+
this.activeSocket = undefined;
|
|
47871
|
+
this.stopHeartbeatCheck();
|
|
47872
|
+
if (this.isClosed) {
|
|
47873
|
+
return;
|
|
47874
|
+
}
|
|
47875
|
+
if (this.drainingSockets.size > 0) {
|
|
47876
|
+
debug5("Draining socket closed after replacement was scheduled");
|
|
47877
|
+
return;
|
|
47878
|
+
}
|
|
47879
|
+
this.handleUnexpectedDisconnect("Connection closed");
|
|
47880
|
+
}
|
|
47881
|
+
handleUnexpectedDisconnect(reason) {
|
|
47882
|
+
this.isConnecting = false;
|
|
47883
|
+
this.notifyConnectionListeners(false, reason);
|
|
47884
|
+
this.scheduleReconnect();
|
|
47885
|
+
}
|
|
47886
|
+
scheduleReconnect(replacement = false) {
|
|
47887
|
+
if (this.isClosed || this.reconnectTimer) {
|
|
47888
|
+
return;
|
|
47889
|
+
}
|
|
47890
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
47891
|
+
this.reconnectTimer = undefined;
|
|
47892
|
+
if (this.isClosed || this.isConnecting || !replacement && this.activeSocket) {
|
|
47893
|
+
return;
|
|
47894
|
+
}
|
|
47895
|
+
this.isConnecting = true;
|
|
47896
|
+
try {
|
|
47897
|
+
const { access_token, team_id } = await this.getOAuthToken();
|
|
47898
|
+
await this.openSocket(access_token, team_id, replacement ? "replacement" : "active");
|
|
47899
|
+
} catch (err) {
|
|
47900
|
+
debug5("Reconnect failed: %O", err);
|
|
47901
|
+
this.isConnecting = false;
|
|
47902
|
+
this.notifyErrorListeners(err);
|
|
47903
|
+
this.scheduleReconnect(replacement);
|
|
47904
|
+
}
|
|
47905
|
+
}, this.reconnectDelay);
|
|
47906
|
+
}
|
|
47907
|
+
scheduleDrainReconnect(retryAfterMs) {
|
|
47908
|
+
if (this.isClosed || this.reconnectTimer) {
|
|
47909
|
+
return;
|
|
47910
|
+
}
|
|
47911
|
+
let safeDelayMs = this.reconnectDelay;
|
|
47912
|
+
if (typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs >= 0 && retryAfterMs <= _Realtime2.MAX_RECONNECT_DELAY_MS) {
|
|
47913
|
+
safeDelayMs = Math.trunc(retryAfterMs);
|
|
47914
|
+
}
|
|
47915
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
47916
|
+
this.reconnectTimer = undefined;
|
|
47917
|
+
if (this.isClosed || this.isConnecting) {
|
|
47918
|
+
return;
|
|
47919
|
+
}
|
|
47920
|
+
this.isConnecting = true;
|
|
47921
|
+
try {
|
|
47922
|
+
const { access_token, team_id } = await this.getOAuthToken();
|
|
47923
|
+
await this.openSocket(access_token, team_id, "replacement");
|
|
47924
|
+
} catch (err) {
|
|
47925
|
+
debug5("Reconnect failed: %O", err);
|
|
47926
|
+
this.isConnecting = false;
|
|
47927
|
+
this.notifyErrorListeners(err);
|
|
47928
|
+
this.scheduleReconnect(true);
|
|
47929
|
+
}
|
|
47930
|
+
}, safeDelayMs);
|
|
47931
|
+
}
|
|
47932
|
+
normalizeReconnectDelay(delay) {
|
|
47933
|
+
if (typeof delay !== "number" || !Number.isFinite(delay)) {
|
|
47934
|
+
return _Realtime2.DEFAULT_RECONNECT_DELAY_MS;
|
|
47935
|
+
}
|
|
47936
|
+
return Math.min(Math.max(0, Math.trunc(delay)), _Realtime2.MAX_RECONNECT_DELAY_MS);
|
|
47937
|
+
}
|
|
47938
|
+
isDuplicateEvent(eventId) {
|
|
47939
|
+
if (!eventId) {
|
|
47940
|
+
return false;
|
|
47941
|
+
}
|
|
47942
|
+
if (this.recentEventIds.has(eventId)) {
|
|
47943
|
+
return true;
|
|
47944
|
+
}
|
|
47945
|
+
this.recentEventIds.add(eventId);
|
|
47946
|
+
this.recentEventIdQueue.push(eventId);
|
|
47947
|
+
if (this.recentEventIdQueue.length > this.maxRecentEventIds) {
|
|
47948
|
+
const expiredId = this.recentEventIdQueue.shift();
|
|
47949
|
+
if (expiredId) {
|
|
47950
|
+
this.recentEventIds.delete(expiredId);
|
|
47951
|
+
}
|
|
47952
|
+
}
|
|
47953
|
+
return false;
|
|
47954
|
+
}
|
|
47762
47955
|
handleHeartbeat() {
|
|
47763
47956
|
debug5("Heartbeat received");
|
|
47764
47957
|
this.lastHeartbeat = Date.now();
|
|
@@ -47785,22 +47978,24 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
|
|
|
47785
47978
|
this.errorListeners.forEach((listener) => {
|
|
47786
47979
|
try {
|
|
47787
47980
|
listener(error48);
|
|
47788
|
-
} catch (
|
|
47789
|
-
debug5("Error in error listener: %O",
|
|
47981
|
+
} catch (listenerError) {
|
|
47982
|
+
debug5("Error in error listener: %O", listenerError);
|
|
47790
47983
|
}
|
|
47791
47984
|
});
|
|
47792
47985
|
}
|
|
47793
47986
|
startHeartbeatCheck() {
|
|
47987
|
+
this.stopHeartbeatCheck();
|
|
47794
47988
|
this.missedHeartbeatCheckTimer = setInterval(() => {
|
|
47795
|
-
if (Date.now() - this.lastHeartbeat > this.missedHeartbeatsLimit) {
|
|
47989
|
+
if (this.activeSocket && Date.now() - this.lastHeartbeat > this.missedHeartbeatsLimit) {
|
|
47796
47990
|
debug5("No heartbeat received in 30 seconds! Closing connection.");
|
|
47797
|
-
this.
|
|
47991
|
+
this.activeSocket.close();
|
|
47798
47992
|
}
|
|
47799
47993
|
}, this.heartbeatInterval);
|
|
47800
47994
|
}
|
|
47801
47995
|
stopHeartbeatCheck() {
|
|
47802
47996
|
if (this.missedHeartbeatCheckTimer) {
|
|
47803
47997
|
clearInterval(this.missedHeartbeatCheckTimer);
|
|
47998
|
+
this.missedHeartbeatCheckTimer = undefined;
|
|
47804
47999
|
}
|
|
47805
48000
|
}
|
|
47806
48001
|
onEvent(listener) {
|
|
@@ -47811,6 +48006,9 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
|
|
|
47811
48006
|
}
|
|
47812
48007
|
onConnection(listener) {
|
|
47813
48008
|
this.connectionListeners.add(listener);
|
|
48009
|
+
if (this.isConnected()) {
|
|
48010
|
+
listener(true);
|
|
48011
|
+
}
|
|
47814
48012
|
return () => {
|
|
47815
48013
|
this.connectionListeners.delete(listener);
|
|
47816
48014
|
};
|
|
@@ -47822,19 +48020,27 @@ var import_debug, __require2, BASE_PATH, BaseAPI = class {
|
|
|
47822
48020
|
};
|
|
47823
48021
|
}
|
|
47824
48022
|
close() {
|
|
47825
|
-
|
|
47826
|
-
|
|
47827
|
-
this.
|
|
47828
|
-
this.
|
|
47829
|
-
}
|
|
48023
|
+
this.isClosed = true;
|
|
48024
|
+
if (this.reconnectTimer) {
|
|
48025
|
+
clearTimeout(this.reconnectTimer);
|
|
48026
|
+
this.reconnectTimer = undefined;
|
|
48027
|
+
}
|
|
48028
|
+
this.stopHeartbeatCheck();
|
|
48029
|
+
this.activeSocket?.close();
|
|
48030
|
+
this.activeSocket = undefined;
|
|
48031
|
+
this.drainingSockets.forEach((socket) => {
|
|
48032
|
+
socket.close();
|
|
48033
|
+
});
|
|
48034
|
+
this.drainingSockets.clear();
|
|
48035
|
+
this.isConnecting = false;
|
|
47830
48036
|
this.eventListeners.clear();
|
|
47831
48037
|
this.connectionListeners.clear();
|
|
47832
48038
|
this.errorListeners.clear();
|
|
47833
48039
|
}
|
|
47834
48040
|
isConnected() {
|
|
47835
|
-
return this.
|
|
48041
|
+
return this.activeSocket?.readyState === WebSocket.OPEN;
|
|
47836
48042
|
}
|
|
47837
|
-
}, UserService = class {
|
|
48043
|
+
}, Realtime, UserService = class {
|
|
47838
48044
|
constructor(client) {
|
|
47839
48045
|
this.client = client;
|
|
47840
48046
|
}
|
|
@@ -48915,6 +49121,9 @@ var init_dist2 = __esm(() => {
|
|
|
48915
49121
|
if (typeof WebSocket === "undefined") {
|
|
48916
49122
|
global.WebSocket = __require2("ws");
|
|
48917
49123
|
}
|
|
49124
|
+
_Realtime.DEFAULT_RECONNECT_DELAY_MS = 5000;
|
|
49125
|
+
_Realtime.MAX_RECONNECT_DELAY_MS = 60000;
|
|
49126
|
+
Realtime = _Realtime;
|
|
48918
49127
|
DEFAULT_POLLING_OPTIONS = {
|
|
48919
49128
|
pollIntervalMs: 1e4,
|
|
48920
49129
|
timeoutMs: 5 * 60 * 1000
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadoa/mcp",
|
|
3
|
-
"version": "0.3.9-rc.
|
|
3
|
+
"version": "0.3.9-rc.2",
|
|
4
4
|
"description": "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run check-types && bun run test:unit && bun run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@kadoa/node-sdk": "^0.
|
|
27
|
+
"@kadoa/node-sdk": "^0.24.2",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
29
|
"express": "^5.2.1",
|
|
30
30
|
"ioredis": "^5.6.1",
|