@bernierllc/chat-suite 1.0.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/.eslintrc.js +26 -0
- package/README.md +542 -0
- package/__tests__/integration/ChatSuite.test.ts +235 -0
- package/__tests__/unit/ConfigManager.test.ts +122 -0
- package/__tests__/unit/MessageOrchestrator.test.ts +223 -0
- package/__tests__/unit/UserManager.test.ts +208 -0
- package/dist/ChatSuite.d.ts +76 -0
- package/dist/ChatSuite.d.ts.map +1 -0
- package/dist/ChatSuite.js +273 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/neverhub/discovery.d.ts +40 -0
- package/dist/neverhub/discovery.d.ts.map +1 -0
- package/dist/neverhub/discovery.js +106 -0
- package/dist/neverhub/event-handlers.d.ts +38 -0
- package/dist/neverhub/event-handlers.d.ts.map +1 -0
- package/dist/neverhub/event-handlers.js +125 -0
- package/dist/neverhub/index.d.ts +4 -0
- package/dist/neverhub/index.d.ts.map +1 -0
- package/dist/neverhub/index.js +26 -0
- package/dist/neverhub/service-registration.d.ts +29 -0
- package/dist/neverhub/service-registration.d.ts.map +1 -0
- package/dist/neverhub/service-registration.js +66 -0
- package/dist/providers/ChatKitProvider.d.ts +53 -0
- package/dist/providers/ChatKitProvider.d.ts.map +1 -0
- package/dist/providers/ChatKitProvider.js +167 -0
- package/dist/providers/ExternalProviders.d.ts +101 -0
- package/dist/providers/ExternalProviders.d.ts.map +1 -0
- package/dist/providers/ExternalProviders.js +153 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +25 -0
- package/dist/services/ConfigManager.d.ts +50 -0
- package/dist/services/ConfigManager.d.ts.map +1 -0
- package/dist/services/ConfigManager.js +95 -0
- package/dist/services/HealthMonitor.d.ts +58 -0
- package/dist/services/HealthMonitor.d.ts.map +1 -0
- package/dist/services/HealthMonitor.js +148 -0
- package/dist/services/MessageOrchestrator.d.ts +63 -0
- package/dist/services/MessageOrchestrator.d.ts.map +1 -0
- package/dist/services/MessageOrchestrator.js +212 -0
- package/dist/services/ProviderManager.d.ts +83 -0
- package/dist/services/ProviderManager.d.ts.map +1 -0
- package/dist/services/ProviderManager.js +204 -0
- package/dist/services/UserManager.d.ts +61 -0
- package/dist/services/UserManager.d.ts.map +1 -0
- package/dist/services/UserManager.js +141 -0
- package/dist/services/index.d.ts +6 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +28 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +26 -0
- package/dist/types/message-types.d.ts +80 -0
- package/dist/types/message-types.d.ts.map +1 -0
- package/dist/types/message-types.js +32 -0
- package/dist/types/provider-types.d.ts +96 -0
- package/dist/types/provider-types.d.ts.map +1 -0
- package/dist/types/provider-types.js +9 -0
- package/dist/types/suite-types.d.ts +101 -0
- package/dist/types/suite-types.d.ts.map +1 -0
- package/dist/types/suite-types.js +9 -0
- package/dist/utils/config-inheritance.d.ts +24 -0
- package/dist/utils/config-inheritance.d.ts.map +1 -0
- package/dist/utils/config-inheritance.js +167 -0
- package/dist/utils/error-handling.d.ts +37 -0
- package/dist/utils/error-handling.d.ts.map +1 -0
- package/dist/utils/error-handling.js +102 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +27 -0
- package/dist/utils/message-bridge.d.ts +68 -0
- package/dist/utils/message-bridge.d.ts.map +1 -0
- package/dist/utils/message-bridge.js +126 -0
- package/dist/utils/user-mapping.d.ts +63 -0
- package/dist/utils/user-mapping.d.ts.map +1 -0
- package/dist/utils/user-mapping.js +110 -0
- package/jest.config.cjs +30 -0
- package/package.json +67 -0
- package/src/ChatSuite.ts +347 -0
- package/src/index.ts +25 -0
- package/src/neverhub/discovery.ts +137 -0
- package/src/neverhub/event-handlers.ts +141 -0
- package/src/neverhub/index.ts +11 -0
- package/src/neverhub/service-registration.ts +89 -0
- package/src/providers/ChatKitProvider.ts +193 -0
- package/src/providers/ExternalProviders.ts +171 -0
- package/src/providers/index.ts +10 -0
- package/src/services/ConfigManager.ts +112 -0
- package/src/services/HealthMonitor.ts +169 -0
- package/src/services/MessageOrchestrator.ts +271 -0
- package/src/services/ProviderManager.ts +247 -0
- package/src/services/UserManager.ts +176 -0
- package/src/services/index.ts +13 -0
- package/src/types/index.ts +11 -0
- package/src/types/message-types.ts +94 -0
- package/src/types/provider-types.ts +116 -0
- package/src/types/suite-types.ts +117 -0
- package/src/utils/config-inheritance.ts +189 -0
- package/src/utils/error-handling.ts +114 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/message-bridge.ts +164 -0
- package/src/utils/user-mapping.ts +132 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.DEFAULT_SUITE_CONFIG = void 0;
|
|
11
|
+
exports.mergeConfigs = mergeConfigs;
|
|
12
|
+
exports.validateConfig = validateConfig;
|
|
13
|
+
exports.getActiveProviders = getActiveProviders;
|
|
14
|
+
/**
|
|
15
|
+
* Default provider configuration
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_PROVIDER_CONFIG = {
|
|
18
|
+
enabled: false,
|
|
19
|
+
priority: 999,
|
|
20
|
+
config: {}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Default chat suite configuration
|
|
24
|
+
*/
|
|
25
|
+
exports.DEFAULT_SUITE_CONFIG = {
|
|
26
|
+
enabled: true,
|
|
27
|
+
providers: {
|
|
28
|
+
chatkit: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
priority: 1,
|
|
31
|
+
config: {
|
|
32
|
+
serviceName: 'chatkit-adapter',
|
|
33
|
+
features: ['streaming', 'attachments', 'threads']
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
aiRouting: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
serviceName: 'chat-ai-router',
|
|
40
|
+
fallbackToHuman: true,
|
|
41
|
+
intentThreshold: 0.8
|
|
42
|
+
},
|
|
43
|
+
analytics: {
|
|
44
|
+
enabled: true,
|
|
45
|
+
serviceName: 'chat-analytics',
|
|
46
|
+
metricsInterval: 60000
|
|
47
|
+
},
|
|
48
|
+
neverhub: {
|
|
49
|
+
enabled: true,
|
|
50
|
+
serviceName: 'chat-suite',
|
|
51
|
+
capabilities: [
|
|
52
|
+
{ type: 'chat', name: 'multi-provider-chat', version: '1.0.0' },
|
|
53
|
+
{ type: 'orchestration', name: 'chat-orchestration', version: '1.0.0' },
|
|
54
|
+
{ type: 'ai', name: 'intelligent-routing', version: '1.0.0' }
|
|
55
|
+
],
|
|
56
|
+
dependencies: ['chat-provider-*', 'chat-ai-router', 'chat-analytics']
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Merge configurations with inheritance
|
|
61
|
+
*/
|
|
62
|
+
function mergeConfigs(baseConfig, overrideConfig) {
|
|
63
|
+
return {
|
|
64
|
+
enabled: overrideConfig.enabled ?? baseConfig.enabled,
|
|
65
|
+
providers: mergeProviderConfigs(baseConfig.providers, overrideConfig.providers),
|
|
66
|
+
aiRouting: overrideConfig.aiRouting ? {
|
|
67
|
+
...baseConfig.aiRouting,
|
|
68
|
+
...overrideConfig.aiRouting
|
|
69
|
+
} : baseConfig.aiRouting,
|
|
70
|
+
analytics: overrideConfig.analytics ? {
|
|
71
|
+
...baseConfig.analytics,
|
|
72
|
+
...overrideConfig.analytics
|
|
73
|
+
} : baseConfig.analytics,
|
|
74
|
+
neverhub: overrideConfig.neverhub ? {
|
|
75
|
+
...baseConfig.neverhub,
|
|
76
|
+
...overrideConfig.neverhub
|
|
77
|
+
} : baseConfig.neverhub,
|
|
78
|
+
messageBridge: overrideConfig.messageBridge ?? baseConfig.messageBridge
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Merge provider configurations
|
|
83
|
+
*/
|
|
84
|
+
function mergeProviderConfigs(baseProviders, overrideProviders) {
|
|
85
|
+
if (!overrideProviders) {
|
|
86
|
+
return baseProviders;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
chatkit: mergeProviderConfig(baseProviders.chatkit, overrideProviders.chatkit),
|
|
90
|
+
slack: mergeProviderConfig(baseProviders.slack, overrideProviders.slack),
|
|
91
|
+
discord: mergeProviderConfig(baseProviders.discord, overrideProviders.discord),
|
|
92
|
+
teams: mergeProviderConfig(baseProviders.teams, overrideProviders.teams)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Merge individual provider configuration
|
|
97
|
+
*/
|
|
98
|
+
function mergeProviderConfig(base, override) {
|
|
99
|
+
if (!override && !base) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const baseConfig = base || DEFAULT_PROVIDER_CONFIG;
|
|
103
|
+
if (!override) {
|
|
104
|
+
return baseConfig;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
enabled: override.enabled ?? baseConfig.enabled,
|
|
108
|
+
priority: override.priority ?? baseConfig.priority,
|
|
109
|
+
config: {
|
|
110
|
+
...baseConfig.config,
|
|
111
|
+
...override.config
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Validate configuration
|
|
117
|
+
*/
|
|
118
|
+
function validateConfig(config) {
|
|
119
|
+
const errors = [];
|
|
120
|
+
// Check that at least one provider is enabled
|
|
121
|
+
const enabledProviders = Object.values(config.providers).filter(p => p?.enabled);
|
|
122
|
+
if (enabledProviders.length === 0) {
|
|
123
|
+
errors.push('At least one provider must be enabled');
|
|
124
|
+
}
|
|
125
|
+
// Validate AI routing config
|
|
126
|
+
if (config.aiRouting?.enabled) {
|
|
127
|
+
if (!config.aiRouting.serviceName) {
|
|
128
|
+
errors.push('AI routing service name is required when AI routing is enabled');
|
|
129
|
+
}
|
|
130
|
+
if (config.aiRouting.intentThreshold !== undefined &&
|
|
131
|
+
(config.aiRouting.intentThreshold < 0 || config.aiRouting.intentThreshold > 1)) {
|
|
132
|
+
errors.push('AI routing intent threshold must be between 0 and 1');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Validate analytics config
|
|
136
|
+
if (config.analytics?.enabled && !config.analytics.serviceName) {
|
|
137
|
+
errors.push('Analytics service name is required when analytics is enabled');
|
|
138
|
+
}
|
|
139
|
+
// Validate NeverHub config
|
|
140
|
+
if (config.neverhub?.enabled) {
|
|
141
|
+
if (!config.neverhub.serviceName) {
|
|
142
|
+
errors.push('NeverHub service name is required when NeverHub is enabled');
|
|
143
|
+
}
|
|
144
|
+
if (!config.neverhub.capabilities || config.neverhub.capabilities.length === 0) {
|
|
145
|
+
errors.push('NeverHub capabilities are required when NeverHub is enabled');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
valid: errors.length === 0,
|
|
150
|
+
errors
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get active providers from configuration
|
|
155
|
+
*/
|
|
156
|
+
function getActiveProviders(config) {
|
|
157
|
+
const providers = [];
|
|
158
|
+
Object.entries(config.providers).forEach(([name, providerConfig]) => {
|
|
159
|
+
if (providerConfig?.enabled) {
|
|
160
|
+
providers.push({
|
|
161
|
+
name,
|
|
162
|
+
priority: providerConfig.priority
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
return providers.sort((a, b) => a.priority - b.priority);
|
|
167
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SuiteResult } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Chat suite error types
|
|
4
|
+
*/
|
|
5
|
+
export declare enum ChatSuiteErrorType {
|
|
6
|
+
PROVIDER_ERROR = "PROVIDER_ERROR",
|
|
7
|
+
ROUTING_ERROR = "ROUTING_ERROR",
|
|
8
|
+
CONFIGURATION_ERROR = "CONFIGURATION_ERROR",
|
|
9
|
+
INITIALIZATION_ERROR = "INITIALIZATION_ERROR",
|
|
10
|
+
MESSAGE_ERROR = "MESSAGE_ERROR",
|
|
11
|
+
NEVERHUB_ERROR = "NEVERHUB_ERROR"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Custom error class for chat suite errors
|
|
15
|
+
*/
|
|
16
|
+
export declare class ChatSuiteError extends Error {
|
|
17
|
+
type: ChatSuiteErrorType;
|
|
18
|
+
originalError?: Error | undefined;
|
|
19
|
+
constructor(type: ChatSuiteErrorType, message: string, originalError?: Error | undefined);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Safely execute an async operation and return a SuiteResult
|
|
23
|
+
*/
|
|
24
|
+
export declare function safeExecute<T>(operation: () => Promise<T>, errorType?: ChatSuiteErrorType): Promise<SuiteResult<T>>;
|
|
25
|
+
/**
|
|
26
|
+
* Retry an operation with exponential backoff
|
|
27
|
+
*/
|
|
28
|
+
export declare function retryOperation<T>(operation: () => Promise<T>, maxRetries?: number, baseDelay?: number): Promise<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Create a standardized error message
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatError(context: string, error: unknown): string;
|
|
33
|
+
/**
|
|
34
|
+
* Check if an error is retryable
|
|
35
|
+
*/
|
|
36
|
+
export declare function isRetryableError(error: unknown): boolean;
|
|
37
|
+
//# sourceMappingURL=error-handling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/utils/error-handling.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;GAEG;AACH,oBAAY,kBAAkB;IAC5B,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,mBAAmB,wBAAwB;IAC3C,oBAAoB,yBAAyB;IAC7C,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;CAClC;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IAE9B,IAAI,EAAE,kBAAkB;IAExB,aAAa,CAAC,EAAE,KAAK;gBAFrB,IAAI,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,EACR,aAAa,CAAC,EAAE,KAAK,YAAA;CAM/B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,SAAS,GAAE,kBAAqD,GAC/D,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAWzB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,UAAU,GAAE,MAAU,EACtB,SAAS,GAAE,MAAa,GACvB,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,GACb,MAAM,CAQR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAYxD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.ChatSuiteError = exports.ChatSuiteErrorType = void 0;
|
|
11
|
+
exports.safeExecute = safeExecute;
|
|
12
|
+
exports.retryOperation = retryOperation;
|
|
13
|
+
exports.formatError = formatError;
|
|
14
|
+
exports.isRetryableError = isRetryableError;
|
|
15
|
+
/**
|
|
16
|
+
* Chat suite error types
|
|
17
|
+
*/
|
|
18
|
+
var ChatSuiteErrorType;
|
|
19
|
+
(function (ChatSuiteErrorType) {
|
|
20
|
+
ChatSuiteErrorType["PROVIDER_ERROR"] = "PROVIDER_ERROR";
|
|
21
|
+
ChatSuiteErrorType["ROUTING_ERROR"] = "ROUTING_ERROR";
|
|
22
|
+
ChatSuiteErrorType["CONFIGURATION_ERROR"] = "CONFIGURATION_ERROR";
|
|
23
|
+
ChatSuiteErrorType["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR";
|
|
24
|
+
ChatSuiteErrorType["MESSAGE_ERROR"] = "MESSAGE_ERROR";
|
|
25
|
+
ChatSuiteErrorType["NEVERHUB_ERROR"] = "NEVERHUB_ERROR";
|
|
26
|
+
})(ChatSuiteErrorType || (exports.ChatSuiteErrorType = ChatSuiteErrorType = {}));
|
|
27
|
+
/**
|
|
28
|
+
* Custom error class for chat suite errors
|
|
29
|
+
*/
|
|
30
|
+
class ChatSuiteError extends Error {
|
|
31
|
+
constructor(type, message, originalError) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.type = type;
|
|
34
|
+
this.originalError = originalError;
|
|
35
|
+
this.name = 'ChatSuiteError';
|
|
36
|
+
Object.setPrototypeOf(this, ChatSuiteError.prototype);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ChatSuiteError = ChatSuiteError;
|
|
40
|
+
/**
|
|
41
|
+
* Safely execute an async operation and return a SuiteResult
|
|
42
|
+
*/
|
|
43
|
+
async function safeExecute(operation, errorType = ChatSuiteErrorType.MESSAGE_ERROR) {
|
|
44
|
+
try {
|
|
45
|
+
const data = await operation();
|
|
46
|
+
return { success: true, data };
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: `${errorType}: ${errorMessage}`
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Retry an operation with exponential backoff
|
|
58
|
+
*/
|
|
59
|
+
async function retryOperation(operation, maxRetries = 3, baseDelay = 1000) {
|
|
60
|
+
let lastError;
|
|
61
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
return await operation();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
lastError = error instanceof Error ? error : new Error('Unknown error');
|
|
67
|
+
if (attempt < maxRetries) {
|
|
68
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
69
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw lastError || new Error('Operation failed after retries');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a standardized error message
|
|
77
|
+
*/
|
|
78
|
+
function formatError(context, error) {
|
|
79
|
+
if (error instanceof ChatSuiteError) {
|
|
80
|
+
return `[${context}] ${error.type}: ${error.message}`;
|
|
81
|
+
}
|
|
82
|
+
if (error instanceof Error) {
|
|
83
|
+
return `[${context}] ${error.message}`;
|
|
84
|
+
}
|
|
85
|
+
return `[${context}] Unknown error: ${String(error)}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if an error is retryable
|
|
89
|
+
*/
|
|
90
|
+
function isRetryableError(error) {
|
|
91
|
+
if (error instanceof ChatSuiteError) {
|
|
92
|
+
return error.type === ChatSuiteErrorType.PROVIDER_ERROR ||
|
|
93
|
+
error.type === ChatSuiteErrorType.MESSAGE_ERROR;
|
|
94
|
+
}
|
|
95
|
+
if (error instanceof Error) {
|
|
96
|
+
const message = error.message.toLowerCase();
|
|
97
|
+
return message.includes('timeout') ||
|
|
98
|
+
message.includes('network') ||
|
|
99
|
+
message.includes('unavailable');
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAQA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
21
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
__exportStar(require("./error-handling"), exports);
|
|
25
|
+
__exportStar(require("./config-inheritance"), exports);
|
|
26
|
+
__exportStar(require("./user-mapping"), exports);
|
|
27
|
+
__exportStar(require("./message-bridge"), exports);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ProviderType, ProviderMessage, MessageBridgeConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Bridged message information
|
|
4
|
+
*/
|
|
5
|
+
export interface BridgedMessage {
|
|
6
|
+
originalMessageId: string;
|
|
7
|
+
sourceProvider: ProviderType;
|
|
8
|
+
targetProvider: ProviderType;
|
|
9
|
+
targetMessageId?: string;
|
|
10
|
+
timestamp: Date;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Message bridge for cross-platform synchronization
|
|
14
|
+
*/
|
|
15
|
+
export declare class MessageBridge {
|
|
16
|
+
private config;
|
|
17
|
+
private bridgedMessages;
|
|
18
|
+
private channelMappings;
|
|
19
|
+
constructor(config: MessageBridgeConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Check if message should be bridged
|
|
22
|
+
*/
|
|
23
|
+
shouldBridge(sourceProvider: ProviderType, targetProvider: ProviderType): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Transform message for target provider
|
|
26
|
+
*/
|
|
27
|
+
transformMessage(message: ProviderMessage, sourceProvider: ProviderType, targetProvider: ProviderType): ProviderMessage;
|
|
28
|
+
/**
|
|
29
|
+
* Record a bridged message
|
|
30
|
+
*/
|
|
31
|
+
recordBridgedMessage(bridgedMessage: BridgedMessage): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get all bridges for a message
|
|
34
|
+
*/
|
|
35
|
+
getBridges(originalMessageId: string): BridgedMessage[];
|
|
36
|
+
/**
|
|
37
|
+
* Add channel mapping
|
|
38
|
+
*/
|
|
39
|
+
addChannelMapping(sourceChannel: string, targetChannel: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get mapped channel
|
|
42
|
+
*/
|
|
43
|
+
getMappedChannel(sourceChannel: string, _sourceProvider: ProviderType, _targetProvider: ProviderType): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Check if reactions should be synced
|
|
46
|
+
*/
|
|
47
|
+
shouldSyncReactions(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Check if edits should be synced
|
|
50
|
+
*/
|
|
51
|
+
shouldSyncEdits(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Check if deletions should be synced
|
|
54
|
+
*/
|
|
55
|
+
shouldSyncDeletions(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Clear all bridged message records
|
|
58
|
+
*/
|
|
59
|
+
clear(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Get statistics
|
|
62
|
+
*/
|
|
63
|
+
getStats(): {
|
|
64
|
+
totalBridged: number;
|
|
65
|
+
bridgesByProvider: Map<ProviderType, number>;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=message-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-bridge.d.ts","sourceRoot":"","sources":["../../src/utils/message-bridge.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,YAAY,CAAC;IAC7B,cAAc,EAAE,YAAY,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,aAAa;IAIZ,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,eAAe,CAAkC;gBAErC,MAAM,EAAE,mBAAmB;IAM/C;;OAEG;IACI,YAAY,CAAC,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,GAAG,OAAO;IASxF;;OAEG;IACI,gBAAgB,CACrB,OAAO,EAAE,eAAe,EACxB,cAAc,EAAE,YAAY,EAC5B,cAAc,EAAE,YAAY,GAC3B,eAAe;IAyBlB;;OAEG;IACI,oBAAoB,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI;IAMjE;;OAEG;IACI,UAAU,CAAC,iBAAiB,EAAE,MAAM,GAAG,cAAc,EAAE;IAI9D;;OAEG;IACI,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAI5E;;OAEG;IACI,gBAAgB,CACrB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,YAAY,EAC7B,eAAe,EAAE,YAAY,GAC5B,MAAM,GAAG,SAAS;IAIrB;;OAEG;IACI,mBAAmB,IAAI,OAAO;IAIrC;;OAEG;IACI,eAAe,IAAI,OAAO;IAIjC;;OAEG;IACI,mBAAmB,IAAI,OAAO;IAIrC;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,QAAQ,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;KAC9C;CAiBF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MessageBridge = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Message bridge for cross-platform synchronization
|
|
13
|
+
*/
|
|
14
|
+
class MessageBridge {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.bridgedMessages = new Map();
|
|
18
|
+
this.channelMappings = new Map();
|
|
19
|
+
if (config.channelMappings) {
|
|
20
|
+
this.channelMappings = config.channelMappings;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if message should be bridged
|
|
25
|
+
*/
|
|
26
|
+
shouldBridge(sourceProvider, targetProvider) {
|
|
27
|
+
if (!this.config.enabled) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return this.config.sourceProviders.includes(sourceProvider) &&
|
|
31
|
+
this.config.targetProviders.includes(targetProvider);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Transform message for target provider
|
|
35
|
+
*/
|
|
36
|
+
transformMessage(message, sourceProvider, targetProvider) {
|
|
37
|
+
const transformed = {
|
|
38
|
+
...message,
|
|
39
|
+
metadata: {
|
|
40
|
+
...message.metadata,
|
|
41
|
+
bridged: true,
|
|
42
|
+
sourceProvider,
|
|
43
|
+
originalContent: message.content
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// Map channel if mapping exists
|
|
47
|
+
if (message.channelId) {
|
|
48
|
+
const mappedChannel = this.getMappedChannel(message.channelId, sourceProvider, targetProvider);
|
|
49
|
+
if (mappedChannel) {
|
|
50
|
+
transformed.channelId = mappedChannel;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Add source provider prefix to content
|
|
54
|
+
transformed.content = `[From ${sourceProvider}] ${message.content}`;
|
|
55
|
+
return transformed;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Record a bridged message
|
|
59
|
+
*/
|
|
60
|
+
recordBridgedMessage(bridgedMessage) {
|
|
61
|
+
const existing = this.bridgedMessages.get(bridgedMessage.originalMessageId) || [];
|
|
62
|
+
existing.push(bridgedMessage);
|
|
63
|
+
this.bridgedMessages.set(bridgedMessage.originalMessageId, existing);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all bridges for a message
|
|
67
|
+
*/
|
|
68
|
+
getBridges(originalMessageId) {
|
|
69
|
+
return this.bridgedMessages.get(originalMessageId) || [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Add channel mapping
|
|
73
|
+
*/
|
|
74
|
+
addChannelMapping(sourceChannel, targetChannel) {
|
|
75
|
+
this.channelMappings.set(sourceChannel, targetChannel);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get mapped channel
|
|
79
|
+
*/
|
|
80
|
+
getMappedChannel(sourceChannel, _sourceProvider, _targetProvider) {
|
|
81
|
+
return this.channelMappings.get(sourceChannel);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if reactions should be synced
|
|
85
|
+
*/
|
|
86
|
+
shouldSyncReactions() {
|
|
87
|
+
return this.config.syncReactions ?? false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if edits should be synced
|
|
91
|
+
*/
|
|
92
|
+
shouldSyncEdits() {
|
|
93
|
+
return this.config.syncEdits ?? false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if deletions should be synced
|
|
97
|
+
*/
|
|
98
|
+
shouldSyncDeletions() {
|
|
99
|
+
return this.config.syncDeletions ?? false;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Clear all bridged message records
|
|
103
|
+
*/
|
|
104
|
+
clear() {
|
|
105
|
+
this.bridgedMessages.clear();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get statistics
|
|
109
|
+
*/
|
|
110
|
+
getStats() {
|
|
111
|
+
const bridgesByProvider = new Map();
|
|
112
|
+
let total = 0;
|
|
113
|
+
this.bridgedMessages.forEach(bridges => {
|
|
114
|
+
bridges.forEach(bridge => {
|
|
115
|
+
const count = bridgesByProvider.get(bridge.targetProvider) || 0;
|
|
116
|
+
bridgesByProvider.set(bridge.targetProvider, count + 1);
|
|
117
|
+
total++;
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
totalBridged: total,
|
|
122
|
+
bridgesByProvider
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.MessageBridge = MessageBridge;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ProviderType } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* User identity across platforms
|
|
4
|
+
*/
|
|
5
|
+
export interface UserIdentity {
|
|
6
|
+
unifiedId: string;
|
|
7
|
+
platformIds: Map<ProviderType, string>;
|
|
8
|
+
displayName?: string;
|
|
9
|
+
email?: string;
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* User mapping storage
|
|
14
|
+
*/
|
|
15
|
+
export declare class UserMapper {
|
|
16
|
+
private identities;
|
|
17
|
+
private providerIndex;
|
|
18
|
+
/**
|
|
19
|
+
* Create or update a user identity
|
|
20
|
+
*/
|
|
21
|
+
mapUser(identity: UserIdentity): void;
|
|
22
|
+
/**
|
|
23
|
+
* Get unified user ID from platform-specific ID
|
|
24
|
+
*/
|
|
25
|
+
getUnifiedId(provider: ProviderType, platformUserId: string): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Get platform-specific user ID from unified ID
|
|
28
|
+
*/
|
|
29
|
+
getPlatformId(unifiedId: string, provider: ProviderType): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Get full user identity
|
|
32
|
+
*/
|
|
33
|
+
getIdentity(unifiedId: string): UserIdentity | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Add platform ID to existing user
|
|
36
|
+
*/
|
|
37
|
+
addPlatformId(unifiedId: string, provider: ProviderType, platformUserId: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Remove user identity
|
|
40
|
+
*/
|
|
41
|
+
removeUser(unifiedId: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Get all users
|
|
44
|
+
*/
|
|
45
|
+
getAllUsers(): UserIdentity[];
|
|
46
|
+
/**
|
|
47
|
+
* Clear all mappings
|
|
48
|
+
*/
|
|
49
|
+
clear(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get number of mapped users
|
|
52
|
+
*/
|
|
53
|
+
size(): number;
|
|
54
|
+
/**
|
|
55
|
+
* Create provider key for indexing
|
|
56
|
+
*/
|
|
57
|
+
private getProviderKey;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a new unified user ID
|
|
61
|
+
*/
|
|
62
|
+
export declare function createUnifiedId(): string;
|
|
63
|
+
//# sourceMappingURL=user-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-mapping.d.ts","sourceRoot":"","sources":["../../src/utils/user-mapping.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,aAAa,CAAkC;IAEvD;;OAEG;IACI,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAU5C;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKvF;;OAEG;IACI,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS;IAKnF;;OAEG;IACI,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI/D;;OAEG;IACI,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO;IAWhG;;OAEG;IACI,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAe7C;;OAEG;IACI,WAAW,IAAI,YAAY,EAAE;IAIpC;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;OAEG;IACI,IAAI,IAAI,MAAM;IAIrB;;OAEG;IACH,OAAO,CAAC,cAAc;CAGvB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|