@xmanrui/dsh-im 0.1.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/LICENSE +21 -0
- package/README.md +143 -0
- package/THIRD_PARTY_NOTICES.md +15 -0
- package/bin/dsh-im.mjs +99 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +6211 -0
- package/lib/index.js +13339 -0
- package/package.json +73 -0
- package/plugin-src/client/build.mjs +38 -0
- package/plugin-src/client/channel-logos.js +107 -0
- package/plugin-src/client/channels/dingtalk/api.js +203 -0
- package/plugin-src/client/channels/dingtalk/index.js +709 -0
- package/plugin-src/client/channels/dingtalk/styles.js +140 -0
- package/plugin-src/client/channels/discord/api.js +11 -0
- package/plugin-src/client/channels/discord/index.js +25 -0
- package/plugin-src/client/channels/discord/styles.js +19 -0
- package/plugin-src/client/channels/feishu/api.js +325 -0
- package/plugin-src/client/channels/feishu/index.js +986 -0
- package/plugin-src/client/channels/feishu/styles.js +505 -0
- package/plugin-src/client/channels/qq/api.js +119 -0
- package/plugin-src/client/channels/qq/index.js +402 -0
- package/plugin-src/client/channels/qq/styles.js +19 -0
- package/plugin-src/client/channels/shared/token-api.js +88 -0
- package/plugin-src/client/channels/shared/token-channel.js +277 -0
- package/plugin-src/client/channels/telegram/api.js +11 -0
- package/plugin-src/client/channels/telegram/index.js +25 -0
- package/plugin-src/client/channels/telegram/styles.js +19 -0
- package/plugin-src/client/channels/wecom/api.js +119 -0
- package/plugin-src/client/channels/wecom/index.js +402 -0
- package/plugin-src/client/channels/wecom/styles.js +19 -0
- package/plugin-src/client/channels/weixin/api.js +156 -0
- package/plugin-src/client/channels/weixin/index.js +577 -0
- package/plugin-src/client/channels/weixin/styles.js +120 -0
- package/plugin-src/client/credential-binding.js +117 -0
- package/plugin-src/client/index.js +192 -0
- package/plugin-src/client/lifecycle.js +86 -0
- package/plugin-src/client/styles.js +192 -0
- package/plugin-src/host/build.mjs +24 -0
- package/plugin-src/host/channels/dingtalk/connection-supervisor.mjs +130 -0
- package/plugin-src/host/channels/dingtalk/index.mjs +39 -0
- package/plugin-src/host/channels/dingtalk/production.mjs +122 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +237 -0
- package/plugin-src/host/channels/discord/index.mjs +30 -0
- package/plugin-src/host/channels/discord/production.mjs +17 -0
- package/plugin-src/host/channels/discord/rpc.mjs +21 -0
- package/plugin-src/host/channels/feishu/connection-supervisor.mjs +167 -0
- package/plugin-src/host/channels/feishu/controller.mjs +172 -0
- package/plugin-src/host/channels/feishu/credential-store.mjs +84 -0
- package/plugin-src/host/channels/feishu/index.mjs +73 -0
- package/plugin-src/host/channels/feishu/production.mjs +138 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +454 -0
- package/plugin-src/host/channels/qq/connection-supervisor.mjs +124 -0
- package/plugin-src/host/channels/qq/index.mjs +30 -0
- package/plugin-src/host/channels/qq/production.mjs +109 -0
- package/plugin-src/host/channels/qq/rpc.mjs +146 -0
- package/plugin-src/host/channels/shared/connection-supervisor.mjs +133 -0
- package/plugin-src/host/channels/shared/production.mjs +104 -0
- package/plugin-src/host/channels/shared/rpc.mjs +119 -0
- package/plugin-src/host/channels/telegram/index.mjs +30 -0
- package/plugin-src/host/channels/telegram/production.mjs +17 -0
- package/plugin-src/host/channels/telegram/rpc.mjs +21 -0
- package/plugin-src/host/channels/wecom/connection-supervisor.mjs +124 -0
- package/plugin-src/host/channels/wecom/index.mjs +36 -0
- package/plugin-src/host/channels/wecom/production.mjs +113 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +151 -0
- package/plugin-src/host/channels/weixin/connection-supervisor.mjs +127 -0
- package/plugin-src/host/channels/weixin/index.mjs +39 -0
- package/plugin-src/host/channels/weixin/production.mjs +119 -0
- package/plugin-src/host/channels/weixin/rpc.mjs +178 -0
- package/plugin-src/host/index.mjs +44 -0
- package/plugin-src/host/rpc-authority.mjs +11 -0
- package/scripts/verify-package.mjs +97 -0
- package/src/channels/dingtalk/config-store.mjs +282 -0
- package/src/channels/dingtalk/device-auth.mjs +237 -0
- package/src/channels/dingtalk/dingtalk-api.mjs +579 -0
- package/src/channels/dingtalk/dingtalk-bridge.mjs +281 -0
- package/src/channels/dingtalk/dingtalk-card-stream.mjs +233 -0
- package/src/channels/dingtalk/dingtalk-controller.mjs +752 -0
- package/src/channels/dingtalk/dingtalk-runtime.mjs +358 -0
- package/src/channels/dingtalk/harness-client.mjs +299 -0
- package/src/channels/dingtalk/state-store.mjs +212 -0
- package/src/channels/discord/config-store.mjs +24 -0
- package/src/channels/discord/discord-api.mjs +153 -0
- package/src/channels/discord/discord-bridge.mjs +15 -0
- package/src/channels/discord/discord-controller.mjs +16 -0
- package/src/channels/discord/discord-runtime.mjs +460 -0
- package/src/channels/discord/harness-client.mjs +3 -0
- package/src/channels/discord/state-store.mjs +3 -0
- package/src/channels/feishu/bridge.mjs +216 -0
- package/src/channels/feishu/config.mjs +71 -0
- package/src/channels/feishu/feishu-app.mjs +51 -0
- package/src/channels/feishu/feishu-channel.mjs +153 -0
- package/src/channels/feishu/feishu-runtime.mjs +222 -0
- package/src/channels/feishu/harness-client.mjs +268 -0
- package/src/channels/feishu/message-utils.mjs +51 -0
- package/src/channels/feishu/multi-bot-controller.mjs +686 -0
- package/src/channels/feishu/plugin-config-store.mjs +204 -0
- package/src/channels/feishu/plugin-controller.mjs +248 -0
- package/src/channels/feishu/registration-manager.mjs +345 -0
- package/src/channels/feishu/state-store.mjs +71 -0
- package/src/channels/qq/config-store.mjs +171 -0
- package/src/channels/qq/harness-client.mjs +3 -0
- package/src/channels/qq/qq-bridge.mjs +177 -0
- package/src/channels/qq/qq-controller.mjs +452 -0
- package/src/channels/qq/qq-runtime.mjs +208 -0
- package/src/channels/qq/qr-auth.mjs +24 -0
- package/src/channels/qq/state-store.mjs +96 -0
- package/src/channels/shared/conversation-state-store.mjs +107 -0
- package/src/channels/shared/editable-message-stream.mjs +81 -0
- package/src/channels/shared/text-harness-bridge.mjs +180 -0
- package/src/channels/shared/token-bot-controller.mjs +298 -0
- package/src/channels/shared/token-config-store.mjs +180 -0
- package/src/channels/telegram/config-store.mjs +24 -0
- package/src/channels/telegram/harness-client.mjs +3 -0
- package/src/channels/telegram/state-store.mjs +3 -0
- package/src/channels/telegram/telegram-api.mjs +120 -0
- package/src/channels/telegram/telegram-bridge.mjs +15 -0
- package/src/channels/telegram/telegram-controller.mjs +16 -0
- package/src/channels/telegram/telegram-runtime.mjs +278 -0
- package/src/channels/wecom/config-store.mjs +170 -0
- package/src/channels/wecom/harness-client.mjs +3 -0
- package/src/channels/wecom/qr-auth.mjs +95 -0
- package/src/channels/wecom/state-store.mjs +90 -0
- package/src/channels/wecom/wecom-bridge.mjs +243 -0
- package/src/channels/wecom/wecom-controller.mjs +474 -0
- package/src/channels/wecom/wecom-runtime.mjs +209 -0
- package/src/channels/weixin/config-store.mjs +182 -0
- package/src/channels/weixin/harness-client.mjs +259 -0
- package/src/channels/weixin/state-store.mjs +112 -0
- package/src/channels/weixin/weixin-api.mjs +319 -0
- package/src/channels/weixin/weixin-bridge.mjs +173 -0
- package/src/channels/weixin/weixin-controller.mjs +545 -0
- package/src/channels/weixin/weixin-runtime.mjs +204 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential references owned by the Feishu Host plugin. They deliberately
|
|
3
|
+
* use DSH's credential provider instead of plugin settings, so the browser's
|
|
4
|
+
* configuration plane can only observe configured/source metadata.
|
|
5
|
+
*/
|
|
6
|
+
export const FEISHU_APP_ID_REF = 'DSH_FEISHU_APP_ID';
|
|
7
|
+
export const FEISHU_APP_SECRET_REF = 'DSH_FEISHU_APP_SECRET';
|
|
8
|
+
|
|
9
|
+
function assertNonEmptyString(value, label) {
|
|
10
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
11
|
+
throw new TypeError(`${label} must be a non-empty string`);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function restore(provider, ref, previous) {
|
|
17
|
+
try {
|
|
18
|
+
if (previous?.value) await provider.set(ref, previous.value);
|
|
19
|
+
else await provider.unset(ref);
|
|
20
|
+
} catch {
|
|
21
|
+
// Preserve the original write failure. The provider remains the source
|
|
22
|
+
// of truth and will report the partial state through describe().
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Adapt the real DSH `ctx.credentials` seam to the small interface consumed
|
|
28
|
+
* by the Feishu controller. Secret values only travel Host-to-Host here.
|
|
29
|
+
*
|
|
30
|
+
* @param {{resolve(Function), describe(Function), set(Function), unset(Function)}} provider
|
|
31
|
+
* @param {{appIdRef?: string, appSecretRef?: string}} options
|
|
32
|
+
*/
|
|
33
|
+
export function createDshCredentialStore(provider, options = {}) {
|
|
34
|
+
if (!provider
|
|
35
|
+
|| typeof provider.resolve !== 'function'
|
|
36
|
+
|| typeof provider.describe !== 'function'
|
|
37
|
+
|| typeof provider.set !== 'function'
|
|
38
|
+
|| typeof provider.unset !== 'function') {
|
|
39
|
+
throw new TypeError('A DSH credential provider is required');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const appIdRef = options.appIdRef ?? FEISHU_APP_ID_REF;
|
|
43
|
+
const appSecretRef = options.appSecretRef ?? FEISHU_APP_SECRET_REF;
|
|
44
|
+
|
|
45
|
+
return Object.freeze({
|
|
46
|
+
async save({ appId, appSecret }) {
|
|
47
|
+
const nextId = assertNonEmptyString(appId, 'Feishu App ID');
|
|
48
|
+
const nextSecret = assertNonEmptyString(appSecret, 'Feishu App Secret');
|
|
49
|
+
const [previousId, previousSecret] = await Promise.all([
|
|
50
|
+
provider.resolve(appIdRef),
|
|
51
|
+
provider.resolve(appSecretRef),
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// Store the secret first. An App ID without its matching secret must
|
|
56
|
+
// never be treated as a usable integration.
|
|
57
|
+
await provider.set(appSecretRef, nextSecret);
|
|
58
|
+
await provider.set(appIdRef, nextId);
|
|
59
|
+
} catch {
|
|
60
|
+
await restore(provider, appSecretRef, previousSecret);
|
|
61
|
+
await restore(provider, appIdRef, previousId);
|
|
62
|
+
throw new Error('Unable to store the Feishu credentials.');
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
async clear() {
|
|
67
|
+
const outcomes = await Promise.allSettled([
|
|
68
|
+
provider.unset(appIdRef),
|
|
69
|
+
provider.unset(appSecretRef),
|
|
70
|
+
]);
|
|
71
|
+
if (outcomes.some((outcome) => outcome.status === 'rejected')) {
|
|
72
|
+
throw new Error('Unable to remove the Feishu credentials.');
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
async configured() {
|
|
77
|
+
const [appId, appSecret] = await Promise.all([
|
|
78
|
+
provider.describe(appIdRef),
|
|
79
|
+
provider.describe(appSecretRef),
|
|
80
|
+
]);
|
|
81
|
+
return appId.configured === true && appSecret.configured === true;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createProvisioningBackedController } from './controller.mjs';
|
|
2
|
+
import { createProductionController } from './production.mjs';
|
|
3
|
+
import { installFeishuRpc } from './rpc.mjs';
|
|
4
|
+
|
|
5
|
+
export const name = 'dsh-feishu-host';
|
|
6
|
+
export const inject = ['connection', 'credentials', 'webServer'];
|
|
7
|
+
|
|
8
|
+
function controllerFrom(ctx, config) {
|
|
9
|
+
if (config?.controller) return config.controller;
|
|
10
|
+
if (typeof config?.createController === 'function') return config.createController();
|
|
11
|
+
if (typeof config?.createProvisioningManager === 'function') {
|
|
12
|
+
return createProvisioningBackedController(config);
|
|
13
|
+
}
|
|
14
|
+
// Cordis deliberately throws when a plugin reads an undeclared service,
|
|
15
|
+
// even through optional chaining. Production uses the explicit services in
|
|
16
|
+
// `inject`; test/programmatic controllers must therefore come from config.
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Cordis/DSH Host plugin entry. Production composition may supply an owned
|
|
22
|
+
* controller service; tests and embedded distributions may inject one through
|
|
23
|
+
* config without changing the Connection RPC boundary.
|
|
24
|
+
*/
|
|
25
|
+
export async function apply(ctx, config = {}) {
|
|
26
|
+
const controller = controllerFrom(ctx, config);
|
|
27
|
+
if (controller) {
|
|
28
|
+
return installFeishuRpc(ctx, controller, config.rpcOptions, config.rpcAuthority);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const production = await createProductionController(ctx, config);
|
|
32
|
+
const disposeRpc = installFeishuRpc(
|
|
33
|
+
ctx,
|
|
34
|
+
production.controller,
|
|
35
|
+
config.rpcOptions,
|
|
36
|
+
config.rpcAuthority,
|
|
37
|
+
);
|
|
38
|
+
ctx.effect(() => async () => {
|
|
39
|
+
await production.close();
|
|
40
|
+
}, 'dsh-feishu: close controller and live connection');
|
|
41
|
+
return disposeRpc;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Create a programmatic plugin module with dependencies closed over. */
|
|
45
|
+
export function createFeishuHostPlugin(config) {
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
name,
|
|
48
|
+
inject,
|
|
49
|
+
apply: (ctx) => apply(ctx, config),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
ProvisioningBackedController,
|
|
55
|
+
createProvisioningBackedController,
|
|
56
|
+
} from './controller.mjs';
|
|
57
|
+
export { createProductionController } from './production.mjs';
|
|
58
|
+
export { ConnectionSupervisor, createConnectionSupervisor } from './connection-supervisor.mjs';
|
|
59
|
+
export { MultiBotDshFeishuController } from '../../../../src/channels/feishu/multi-bot-controller.mjs';
|
|
60
|
+
export {
|
|
61
|
+
FEISHU_APP_ID_REF,
|
|
62
|
+
FEISHU_APP_SECRET_REF,
|
|
63
|
+
createDshCredentialStore,
|
|
64
|
+
} from './credential-store.mjs';
|
|
65
|
+
export {
|
|
66
|
+
FEISHU_ENDPOINTS,
|
|
67
|
+
FEISHU_MULTI_ENDPOINTS,
|
|
68
|
+
FEISHU_RPC_CHANNEL,
|
|
69
|
+
FEISHU_RPC_ENDPOINTS,
|
|
70
|
+
createFeishuRpcHandler,
|
|
71
|
+
installFeishuRpc,
|
|
72
|
+
toPublicFeishuStatus,
|
|
73
|
+
} from './rpc.mjs';
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { unlink } from 'node:fs/promises';
|
|
4
|
+
import * as Lark from '@larksuiteoapi/node-sdk';
|
|
5
|
+
import { createConnectionSupervisor } from './connection-supervisor.mjs';
|
|
6
|
+
import { verifyFeishuApp } from '../../../../src/channels/feishu/feishu-app.mjs';
|
|
7
|
+
import { FeishuRuntime } from '../../../../src/channels/feishu/feishu-runtime.mjs';
|
|
8
|
+
import { HarnessClient } from '../../../../src/channels/feishu/harness-client.mjs';
|
|
9
|
+
import {
|
|
10
|
+
LEGACY_FEISHU_SECRET_REF,
|
|
11
|
+
PluginConfigStore,
|
|
12
|
+
} from '../../../../src/channels/feishu/plugin-config-store.mjs';
|
|
13
|
+
import { MultiBotDshFeishuController } from '../../../../src/channels/feishu/multi-bot-controller.mjs';
|
|
14
|
+
import { StateStore } from '../../../../src/channels/feishu/state-store.mjs';
|
|
15
|
+
|
|
16
|
+
function harnessOrigin(webServer, configured) {
|
|
17
|
+
if (configured !== undefined) return new URL(configured);
|
|
18
|
+
const port = webServer?.port;
|
|
19
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
|
|
20
|
+
throw new Error('dsh-feishu requires an initialized DSH webServer port');
|
|
21
|
+
}
|
|
22
|
+
// Even when DSH listens on all interfaces, its own plugin talks through the
|
|
23
|
+
// loopback authority accepted by Connection's request-trust fence.
|
|
24
|
+
return new URL(`http://127.0.0.1:${port}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function pluginPaths(config) {
|
|
28
|
+
const dshHome = resolve(config.dshHome
|
|
29
|
+
?? process.env.DSH_HOME
|
|
30
|
+
?? join(homedir(), '.dsh'));
|
|
31
|
+
const root = resolve(config.dataDir ?? join(dshHome, 'integrations', 'dsh-feishu'));
|
|
32
|
+
return {
|
|
33
|
+
root,
|
|
34
|
+
config: resolve(config.configPath ?? join(root, 'config.json')),
|
|
35
|
+
legacyState: resolve(config.statePath ?? join(root, 'state.json')),
|
|
36
|
+
bots: resolve(config.botsDir ?? join(root, 'bots')),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Assemble the production controller from DSH Host services and local plugin
|
|
42
|
+
* classes. No bridge process or environment App credentials are required.
|
|
43
|
+
*/
|
|
44
|
+
export async function createProductionController(ctx, config = {}, internals = {}) {
|
|
45
|
+
if (!ctx?.credentials) throw new TypeError('dsh-feishu requires ctx.credentials');
|
|
46
|
+
if (!ctx?.webServer) throw new TypeError('dsh-feishu requires ctx.webServer');
|
|
47
|
+
|
|
48
|
+
const lark = internals.lark ?? Lark;
|
|
49
|
+
const Controller = internals.Controller ?? MultiBotDshFeishuController;
|
|
50
|
+
const ConfigStore = internals.ConfigStore ?? PluginConfigStore;
|
|
51
|
+
const SessionStateStore = internals.StateStore ?? StateStore;
|
|
52
|
+
const Harness = internals.HarnessClient ?? HarnessClient;
|
|
53
|
+
const Runtime = internals.FeishuRuntime ?? FeishuRuntime;
|
|
54
|
+
const verifyApp = internals.verifyFeishuApp ?? verifyFeishuApp;
|
|
55
|
+
const createSupervisor = internals.createConnectionSupervisor ?? createConnectionSupervisor;
|
|
56
|
+
const logger = typeof ctx.logger === 'function'
|
|
57
|
+
? ctx.logger('dsh-feishu')
|
|
58
|
+
: (ctx.logger ?? console);
|
|
59
|
+
const paths = pluginPaths(config);
|
|
60
|
+
const configStore = await new ConfigStore(paths.config).load();
|
|
61
|
+
// State is lazy per bot. A corrupt legacy file can therefore fail only the
|
|
62
|
+
// migrated bot and cannot prevent healthy v2 bots from starting.
|
|
63
|
+
const stateStores = new Map();
|
|
64
|
+
const statePathFor = (botConfig) => !botConfig.id
|
|
65
|
+
|| !botConfig.secretRef
|
|
66
|
+
|| botConfig.secretRef === LEGACY_FEISHU_SECRET_REF
|
|
67
|
+
? paths.legacyState
|
|
68
|
+
: resolve(paths.bots, botConfig.id, 'state.json');
|
|
69
|
+
const stateFor = async (botConfig) => {
|
|
70
|
+
const stateKey = botConfig.id ?? '__legacy__';
|
|
71
|
+
let state = stateStores.get(stateKey);
|
|
72
|
+
if (!state) {
|
|
73
|
+
state = await new SessionStateStore(statePathFor(botConfig)).load();
|
|
74
|
+
stateStores.set(stateKey, state);
|
|
75
|
+
}
|
|
76
|
+
return state;
|
|
77
|
+
};
|
|
78
|
+
const harness = new Harness({
|
|
79
|
+
baseUrl: harnessOrigin(ctx.webServer, config.harnessBaseUrl),
|
|
80
|
+
workspace: resolve(config.workspace ?? process.cwd()),
|
|
81
|
+
agentPreset: config.agentPreset ?? 'standard',
|
|
82
|
+
// This plugin is already hosted by a running DSH process. Starting a
|
|
83
|
+
// second DSH would create a competing server and lifecycle.
|
|
84
|
+
autostart: false,
|
|
85
|
+
dshBin: config.dshBin ?? 'dsh',
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const controller = new Controller({
|
|
89
|
+
registerApp: (options) => lark.registerApp(options),
|
|
90
|
+
verifyApp,
|
|
91
|
+
credentials: ctx.credentials,
|
|
92
|
+
configStore,
|
|
93
|
+
createRuntime: async ({ botId, config: botConfig, appSecret }) => {
|
|
94
|
+
const state = await stateFor(botConfig);
|
|
95
|
+
return new Runtime({
|
|
96
|
+
lark,
|
|
97
|
+
appId: botConfig.appId,
|
|
98
|
+
appSecret,
|
|
99
|
+
domain: botConfig.domain,
|
|
100
|
+
ownerOpenIds: botConfig.ownerOpenIds ?? [botConfig.ownerOpenId],
|
|
101
|
+
harness,
|
|
102
|
+
state,
|
|
103
|
+
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
104
|
+
logger: {
|
|
105
|
+
error: (...args) => logger.error?.(`[${botId ?? botConfig.id}]`, ...args),
|
|
106
|
+
warn: (...args) => logger.warn?.(`[${botId ?? botConfig.id}]`, ...args),
|
|
107
|
+
info: (...args) => logger.info?.(`[${botId ?? botConfig.id}]`, ...args),
|
|
108
|
+
debug: (...args) => logger.debug?.(`[${botId ?? botConfig.id}]`, ...args),
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
deleteState: async ({ botId, config: botConfig }) => {
|
|
113
|
+
stateStores.delete(botId);
|
|
114
|
+
try {
|
|
115
|
+
await unlink(statePathFor(botConfig));
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const supervisor = createSupervisor({
|
|
123
|
+
controller,
|
|
124
|
+
harness,
|
|
125
|
+
logger,
|
|
126
|
+
retryDelaysMs: config.retryDelaysMs,
|
|
127
|
+
healthyIntervalMs: config.healthyIntervalMs,
|
|
128
|
+
}).start();
|
|
129
|
+
return {
|
|
130
|
+
controller,
|
|
131
|
+
ready: supervisor.ready,
|
|
132
|
+
async close() {
|
|
133
|
+
await supervisor.close();
|
|
134
|
+
await controller.close();
|
|
135
|
+
harness.stopManagedProcess();
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|