@xmanrui/dsh-im 4.22.0 → 4.24.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.en.md +5 -4
- package/README.md +5 -4
- package/lib/client.js +2584 -1153
- package/lib/index.js +290 -298
- package/package.json +14 -2
- package/plugin-src/client/channel-card-meta.js +2 -0
- package/plugin-src/client/channel-logos.js +11 -0
- package/plugin-src/client/channels/dingtalk/api.js +5 -1
- package/plugin-src/client/channels/dingtalk/index.js +15 -13
- package/plugin-src/client/channels/email/api.js +52 -0
- package/plugin-src/client/channels/email/index.js +728 -0
- package/plugin-src/client/channels/email/styles.js +51 -0
- package/plugin-src/client/channels/feishu/api.js +4 -2
- package/plugin-src/client/channels/feishu/index.js +23 -7
- package/plugin-src/client/channels/imessage/index.js +2 -1
- package/plugin-src/client/channels/office/api.js +2 -0
- package/plugin-src/client/channels/office/index.js +6 -5
- package/plugin-src/client/channels/qq/api.js +7 -0
- package/plugin-src/client/channels/qq/index.js +16 -3
- package/plugin-src/client/channels/shared/token-api.js +8 -1
- package/plugin-src/client/channels/shared/token-channel.js +28 -3
- package/plugin-src/client/channels/slack/index.js +2 -1
- package/plugin-src/client/channels/telegram/index.js +3 -0
- package/plugin-src/client/channels/telegram/styles.js +12 -0
- package/plugin-src/client/channels/telegram/thinking-traces.js +25 -0
- package/plugin-src/client/channels/wecom/api.js +7 -1
- package/plugin-src/client/channels/wecom/index.js +16 -3
- package/plugin-src/client/channels/wecom-app/api.js +6 -1
- package/plugin-src/client/channels/wecom-app/index.js +16 -3
- package/plugin-src/client/channels/weixin/api.js +2 -1
- package/plugin-src/client/channels/weixin/connection-error.js +1 -71
- package/plugin-src/client/channels/whatsapp/api.js +5 -0
- package/plugin-src/client/channels/whatsapp/index.js +16 -3
- package/plugin-src/client/connection-error.js +87 -0
- package/plugin-src/client/global-settings.js +81 -1
- package/plugin-src/client/i18n.js +69 -1
- package/plugin-src/client/index.js +40 -4
- package/plugin-src/client/last-message-error.js +2 -1
- package/plugin-src/client/styles.js +8 -2
- package/plugin-src/host/build.mjs +4 -0
- package/plugin-src/host/channels/dingtalk/production.mjs +2 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +7 -4
- package/plugin-src/host/channels/email/availability.mjs +60 -0
- package/plugin-src/host/channels/email/index.mjs +36 -0
- package/plugin-src/host/channels/email/production.mjs +58 -0
- package/plugin-src/host/channels/email/rpc.mjs +163 -0
- package/plugin-src/host/channels/feishu/production.mjs +3 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +7 -4
- package/plugin-src/host/channels/imessage/rpc.mjs +13 -6
- package/plugin-src/host/channels/office/rpc.mjs +3 -1
- package/plugin-src/host/channels/qq/production.mjs +2 -0
- package/plugin-src/host/channels/qq/rpc.mjs +5 -3
- package/plugin-src/host/channels/shared/production.mjs +52 -5
- package/plugin-src/host/channels/shared/rpc.mjs +14 -3
- package/plugin-src/host/channels/shared/startup-error.mjs +4 -3
- package/plugin-src/host/channels/shared/startup.mjs +11 -6
- package/plugin-src/host/channels/shared/thinking-traces-rpc.mjs +11 -0
- package/plugin-src/host/channels/slack/production.mjs +2 -0
- package/plugin-src/host/channels/slack/rpc.mjs +5 -3
- package/plugin-src/host/channels/wecom/production.mjs +2 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +5 -3
- package/plugin-src/host/channels/wecom-app/production.mjs +2 -0
- package/plugin-src/host/channels/wecom-app/rpc.mjs +5 -3
- package/plugin-src/host/channels/weixin/production.mjs +2 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +2 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +5 -3
- package/plugin-src/host/delivery-adapter.mjs +11 -0
- package/plugin-src/host/image-input-rpc.mjs +24 -0
- package/plugin-src/host/inbound-ttl-rpc.mjs +6 -1
- package/plugin-src/host/index.mjs +3 -0
- package/plugin-src/host/modern-harness-api.mjs +7 -2
- package/plugin-src/management-rpc.mjs +12 -2
- package/scripts/verify-package.mjs +13 -5
- package/src/channels/dingtalk/connection-error.mjs +5 -12
- package/src/channels/dingtalk/device-auth.mjs +4 -1
- package/src/channels/dingtalk/dingtalk-bridge.mjs +6 -4
- package/src/channels/dingtalk/dingtalk-controller.mjs +60 -45
- package/src/channels/dingtalk/dingtalk-runtime.mjs +20 -4
- package/src/channels/discord/discord-api.mjs +3 -3
- package/src/channels/discord/discord-runtime.mjs +18 -12
- package/src/channels/email/config-store.mjs +194 -0
- package/src/channels/email/email-api.mjs +20 -0
- package/src/channels/email/email-bridge.mjs +17 -0
- package/src/channels/email/email-controller.mjs +824 -0
- package/src/channels/email/email-runtime.mjs +699 -0
- package/src/channels/email/harness-client.mjs +7 -0
- package/src/channels/email/mail-format.mjs +91 -0
- package/src/channels/email/state-store.mjs +176 -0
- package/src/channels/email/transport.mjs +64 -0
- package/src/channels/email/transports/agent-mail.mjs +604 -0
- package/src/channels/email/transports/agently-cli.mjs +288 -0
- package/src/channels/email/transports/imap-smtp.mjs +165 -0
- package/src/channels/feishu/bridge.mjs +39 -11
- package/src/channels/feishu/feishu-channel.mjs +35 -0
- package/src/channels/feishu/feishu-runtime.mjs +15 -8
- package/src/channels/feishu/group-message-permission-manager.mjs +2 -1
- package/src/channels/feishu/live-cot.mjs +260 -0
- package/src/channels/feishu/message-utils.mjs +3 -2
- package/src/channels/feishu/multi-bot-controller.mjs +56 -47
- package/src/channels/feishu/registration-manager.mjs +8 -4
- package/src/channels/feishu/repair-manager.mjs +2 -1
- package/src/channels/feishu/slash-command-registry.mjs +17 -0
- package/src/channels/feishu/step-push-mode.mjs +10 -4
- package/src/channels/imessage/runtime.mjs +9 -5
- package/src/channels/office/office-controller.mjs +23 -12
- package/src/channels/office/office-runtime.mjs +6 -3
- package/src/channels/office/office-transport.mjs +1 -0
- package/src/channels/qq/qq-bridge.mjs +7 -5
- package/src/channels/qq/qq-controller.mjs +56 -42
- package/src/channels/qq/qq-runtime.mjs +16 -11
- package/src/channels/shared/bot-workspace-store.mjs +29 -10
- package/src/channels/shared/connection-error.mjs +191 -0
- package/src/channels/shared/connection-test.mjs +3 -1
- package/src/channels/shared/conversation-state-store.mjs +46 -1
- package/src/channels/shared/diagnostic-details.mjs +95 -0
- package/src/channels/shared/harness-client.mjs +287 -57
- package/src/channels/shared/i18n-en/diagnostics.mjs +55 -0
- package/src/channels/shared/i18n-en/email.mjs +25 -0
- package/src/channels/shared/i18n-en/image-input.mjs +17 -0
- package/src/channels/shared/i18n-en/shared-a.mjs +1 -0
- package/src/channels/shared/i18n-en/shared-c.mjs +1 -1
- package/src/channels/shared/i18n-en.mjs +6 -0
- package/src/channels/shared/image-input-policy.mjs +35 -0
- package/src/channels/shared/image-input-settings-store.mjs +60 -0
- package/src/channels/shared/image-input.mjs +124 -0
- package/src/channels/shared/image-prompt.mjs +15 -7
- package/src/channels/shared/message-failure.mjs +12 -0
- package/src/channels/shared/semantic/reply-reference.mjs +3 -3
- package/src/channels/shared/text-harness-bridge.mjs +150 -25
- package/src/channels/shared/token-bot-controller.mjs +52 -47
- package/src/channels/slack/slack-api.mjs +3 -3
- package/src/channels/slack/slack-controller.mjs +59 -51
- package/src/channels/slack/slack-runtime.mjs +18 -12
- package/src/channels/telegram/config-store.mjs +4 -1
- package/src/channels/telegram/telegram-api.mjs +2 -2
- package/src/channels/telegram/telegram-controller.mjs +13 -1
- package/src/channels/telegram/telegram-runtime.mjs +215 -14
- package/src/channels/wecom/wecom-bridge.mjs +15 -6
- package/src/channels/wecom/wecom-controller.mjs +51 -37
- package/src/channels/wecom/wecom-runtime.mjs +10 -6
- package/src/channels/wecom-app/wecom-app-bridge.mjs +7 -5
- package/src/channels/wecom-app/wecom-app-controller.mjs +50 -37
- package/src/channels/wecom-app/wecom-app-runtime.mjs +2 -1
- package/src/channels/weixin/connection-error.mjs +26 -92
- package/src/channels/weixin/diagnostic-details.mjs +1 -63
- package/src/channels/weixin/weixin-bridge.mjs +7 -5
- package/src/channels/whatsapp/whatsapp-controller.mjs +34 -17
- package/src/channels/whatsapp/whatsapp-runtime.mjs +35 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmanrui/dsh-im",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.0",
|
|
4
4
|
"description": "把十一种 IM 渠道和公网 AI Office 接入本机 DeepSeek Harness。 Connect eleven IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -110,7 +110,12 @@
|
|
|
110
110
|
"cordis.patch.yml",
|
|
111
111
|
"lib",
|
|
112
112
|
"plugin-src",
|
|
113
|
-
"scripts",
|
|
113
|
+
"scripts/verify-interface-language.mjs",
|
|
114
|
+
"scripts/verify-lan-management.mjs",
|
|
115
|
+
"scripts/verify-model-setting.mjs",
|
|
116
|
+
"scripts/verify-package.mjs",
|
|
117
|
+
"scripts/verify-session-channel-logos.mjs",
|
|
118
|
+
"scripts/verify-session-title-prefix.mjs",
|
|
114
119
|
"src",
|
|
115
120
|
"PROACTIVE_DELIVERY.md",
|
|
116
121
|
"PROACTIVE_DELIVERY.en.md",
|
|
@@ -161,6 +166,9 @@
|
|
|
161
166
|
"@tencent-connect/qqbot-nodejs": "1.0.4",
|
|
162
167
|
"@wecom/aibot-node-sdk": "1.0.7",
|
|
163
168
|
"dingtalk-stream": "2.1.4",
|
|
169
|
+
"imapflow": "^2.0.5",
|
|
170
|
+
"mailparser": "^3.9.28",
|
|
171
|
+
"nodemailer": "^10.0.10",
|
|
164
172
|
"qrcode": "1.5.4",
|
|
165
173
|
"undici": "7.29.0"
|
|
166
174
|
},
|
|
@@ -179,5 +187,9 @@
|
|
|
179
187
|
"doc": "docs",
|
|
180
188
|
"lib": "lib",
|
|
181
189
|
"test": "test"
|
|
190
|
+
},
|
|
191
|
+
"optionalDependencies": {
|
|
192
|
+
"@tencent-qqmail/agently-cli": "^1.0.18",
|
|
193
|
+
"sharp": "0.35.4"
|
|
182
194
|
}
|
|
183
195
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ConnectionError } from './connection-error.js';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
|
|
3
4
|
import { h, isEnglish } from './i18n.js';
|
|
@@ -124,6 +125,7 @@ export function LastMessageErrorSummary({ className = '', error }) {
|
|
|
124
125
|
h('strong', null, '最近一条消息处理失败'),
|
|
125
126
|
':',
|
|
126
127
|
h('span', null, error.message),
|
|
128
|
+
error.details ? h(ConnectionError, { error, showMessage: false }) : null,
|
|
127
129
|
'(',
|
|
128
130
|
h('span', null, '错误码'),
|
|
129
131
|
` ${error.code} · `,
|
|
@@ -166,3 +166,14 @@ export function OfficeLogoGlyph({ size } = {}) {
|
|
|
166
166
|
h('path', { fill: 'currentColor', d: 'M4 3.5h10.5a2 2 0 0 1 2 2v13H4v-15Zm2.2 3v1.8h2V6.5h-2Zm4.1 0v1.8h2V6.5h-2Zm-4.1 4v1.8h2v-1.8h-2Zm4.1 0v1.8h2v-1.8h-2ZM8.4 15v3.5h3V15h-3Z' }),
|
|
167
167
|
h('path', { fill: 'currentColor', d: 'M18.3 8.2h1.5v3h3v1.5h-3v3h-1.5v-3h-3v-1.5h3v-3Z' }));
|
|
168
168
|
}
|
|
169
|
+
|
|
170
|
+
export function EmailLogoGlyph({ size } = {}) {
|
|
171
|
+
return h('svg', {
|
|
172
|
+
...dimensions(size),
|
|
173
|
+
viewBox: '0 0 24 24',
|
|
174
|
+
focusable: 'false',
|
|
175
|
+
'aria-hidden': 'true',
|
|
176
|
+
'data-im-channel-logo': 'email',
|
|
177
|
+
},
|
|
178
|
+
h('path', { fill: 'currentColor', d: 'M3.2 5.6h17.6c.66 0 1.2.54 1.2 1.2v10.4c0 .66-.54 1.2-1.2 1.2H3.2A1.2 1.2 0 0 1 2 17.2V6.8c0-.66.54-1.2 1.2-1.2Zm.9 1.7v.28L12 12.3l7.9-4.72V7.3H4.1Zm15.8 2.02-7.42 4.43a1 1 0 0 1-1.06 0L4.1 9.32v7.78h15.8V9.32Z' }));
|
|
179
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeConnectionError as normalizeTestError } from '../../connection-error.js';
|
|
2
|
+
import { diagnosticFields } from '../../../../src/channels/shared/diagnostic-details.mjs';
|
|
1
3
|
import { normalizeBotAlias } from '../../../../src/channels/shared/bot-alias.mjs';
|
|
2
4
|
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
|
|
3
5
|
import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
|
|
@@ -99,6 +101,7 @@ function normalizeError(value, fallbackCode, fallbackMessage) {
|
|
|
99
101
|
const hint = sanitizeMessage(value.hint, '');
|
|
100
102
|
const referenceId = safeReferenceId(value.referenceId);
|
|
101
103
|
return {
|
|
104
|
+
...diagnosticFields(value),
|
|
102
105
|
code: safeErrorCode(value.code, fallbackCode),
|
|
103
106
|
message: sanitizeMessage(value.message, fallbackMessage),
|
|
104
107
|
...(hint ? { hint } : {}),
|
|
@@ -113,7 +116,7 @@ function normalizeTestMessage(value) {
|
|
|
113
116
|
const code = value.code === 'test-target-unavailable'
|
|
114
117
|
? 'test-target-unavailable'
|
|
115
118
|
: 'test-message-failed';
|
|
116
|
-
return { sent: false, code };
|
|
119
|
+
return { sent: false, code, ...(value.error ? { error: normalizeTestError(value.error) } : {}) };
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
export function unwrapRpcResult(result) {
|
|
@@ -130,6 +133,7 @@ export function unwrapRpcResult(result) {
|
|
|
130
133
|
error.code = visible.code;
|
|
131
134
|
if (visible.hint) error.hint = visible.hint;
|
|
132
135
|
if (visible.referenceId) error.referenceId = visible.referenceId;
|
|
136
|
+
Object.assign(error, diagnosticFields(result.error));
|
|
133
137
|
throw error;
|
|
134
138
|
}
|
|
135
139
|
return result.value;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ConnectionError, normalizeConnectionError } from '../../connection-error.js';
|
|
1
2
|
import { BotName } from '../../bot-alias.js';
|
|
2
3
|
import * as React from 'react';
|
|
3
4
|
|
|
@@ -176,16 +177,7 @@ function ProgressPanel({ status, busy, onCancel }) {
|
|
|
176
177
|
h(Button, { onClick: onCancel, disabled: busy }, '取消接入')));
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
function ConnectionErrorDiagnostic({ error }) {
|
|
180
|
-
if (!error) return null;
|
|
181
|
-
return h('div', { className: 'ddt-errorDiagnostic' },
|
|
182
|
-
error.hint ? h('p', { className: 'ddt-errorHint' }, error.hint) : null,
|
|
183
|
-
h('span', { className: 'ddt-errorCode' },
|
|
184
|
-
h('span', null, '错误码'), `: ${error.code}`,
|
|
185
|
-
error.referenceId
|
|
186
|
-
? h(React.Fragment, null, ' · ', h('span', null, '参考号'), `: ${error.referenceId}`)
|
|
187
|
-
: null));
|
|
188
|
-
}
|
|
180
|
+
function ConnectionErrorDiagnostic({ error }) { return error ? h(ConnectionError, { error, showMessage: false }) : null; }
|
|
189
181
|
|
|
190
182
|
function ProvisionError({ provision, busy, onRetry, onClose }) {
|
|
191
183
|
const error = provision.error ?? {
|
|
@@ -198,8 +190,7 @@ function ProvisionError({ provision, busy, onRetry, onClose }) {
|
|
|
198
190
|
h('h3', null, provision.status === 'expired'
|
|
199
191
|
? '二维码已过期'
|
|
200
192
|
: connectionFailed ? '机器人已保存,但连接未就绪' : '钉钉机器人没有接入完成'),
|
|
201
|
-
h(
|
|
202
|
-
h(ConnectionErrorDiagnostic, { error }),
|
|
193
|
+
h(ConnectionError, { error }),
|
|
203
194
|
h('div', { className: 'ddt-actions dim-viewActions' },
|
|
204
195
|
connectionFailed
|
|
205
196
|
? h(Button, { kind: 'primary', onClick: onClose, disabled: busy }, '查看已保存的机器人')
|
|
@@ -364,6 +355,7 @@ function AccountList(props) {
|
|
|
364
355
|
const EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
|
|
365
356
|
|
|
366
357
|
export function DingtalkSettingsTab({ rpcCall }) {
|
|
358
|
+
const [operationError, setOperationError] = React.useState(null);
|
|
367
359
|
const [model, setModel] = React.useState({
|
|
368
360
|
phase: 'loading', bots: [], totals: EMPTY_TOTALS, revision: 0, error: null,
|
|
369
361
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
@@ -445,7 +437,16 @@ export function DingtalkSettingsTab({ rpcCall }) {
|
|
|
445
437
|
|
|
446
438
|
const invoke = React.useCallback(async (endpoint, payload = {}, signal) => {
|
|
447
439
|
if (typeof rpcCall !== 'function') throw new TypeError('钉钉设置页缺少 RPC 连接');
|
|
448
|
-
|
|
440
|
+
const operation = !['connection.status', 'provision.poll', 'provision.begin', 'provision.cancel'].includes(endpoint);
|
|
441
|
+
if (operation && mountedRef.current) setOperationError(null);
|
|
442
|
+
try {
|
|
443
|
+
const value = unwrapRpcResult(await rpcCall(endpoint, payload, signal));
|
|
444
|
+
if (operation && mountedRef.current) setOperationError(value?.testMessage?.error ?? value?.warnings?.[0] ?? null);
|
|
445
|
+
return value;
|
|
446
|
+
} catch (error) {
|
|
447
|
+
if (endpoint === 'bot.delete' && mountedRef.current && !signal?.aborted && error?.name !== 'AbortError') setOperationError(normalizeConnectionError(error));
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
449
450
|
}, [rpcCall]);
|
|
450
451
|
|
|
451
452
|
const loadStatus = React.useCallback(async ({
|
|
@@ -896,6 +897,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
|
|
|
896
897
|
}, h(AgentPresetCatalogContext.Provider, {
|
|
897
898
|
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
898
899
|
}, h('section', { className: 'ddt-page dim-channelPage', 'aria-label': '钉钉设置' },
|
|
900
|
+
operationError ? h(ConnectionError, { error: operationError }) : null,
|
|
899
901
|
h(Heading, {
|
|
900
902
|
totals: model.totals,
|
|
901
903
|
adding: Boolean(provision),
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TOKEN_BOT_ENDPOINTS, createTokenChannelApi } from '../shared/token-api.js';
|
|
2
|
+
|
|
3
|
+
export const EMAIL_RPC_CHANNEL = '/email';
|
|
4
|
+
export const EMAIL_ENDPOINTS = Object.freeze({
|
|
5
|
+
...TOKEN_BOT_ENDPOINTS,
|
|
6
|
+
// Asks the Host whether the channel is enabled. An explicitly disabled
|
|
7
|
+
// channel hides its access entry point.
|
|
8
|
+
availability: 'channel.availability',
|
|
9
|
+
// The mailbox binds by address + app password rather than a single token.
|
|
10
|
+
bindCredentials: 'bot.bind-mailbox',
|
|
11
|
+
updateMailbox: 'bot.mailbox.update',
|
|
12
|
+
// Session binding controls (per-account settings panel).
|
|
13
|
+
startAuth: 'bot.auth.start',
|
|
14
|
+
pollAuth: 'bot.auth.poll',
|
|
15
|
+
getBinding: 'bot.session-binding.get',
|
|
16
|
+
setBinding: 'bot.session-binding.set',
|
|
17
|
+
listSessions: 'bot.session.list',
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Carry the channel-specific mailbox fields through the shared snapshot
|
|
21
|
+
* normalizer, which keeps an explicit field list and would otherwise drop
|
|
22
|
+
* them — the settings form then showed an empty allowlist even though the
|
|
23
|
+
* Host was returning it.
|
|
24
|
+
*/
|
|
25
|
+
function normalizeEmailBotExtension(value) {
|
|
26
|
+
const senders = Array.isArray(value?.allowedSenders) ? value.allowedSenders : [];
|
|
27
|
+
return {
|
|
28
|
+
allowedSenders: senders.filter((entry) => typeof entry === 'string' && entry),
|
|
29
|
+
// Without this the settings page cannot tell an Agent mailbox from an
|
|
30
|
+
// IMAP/SMTP one, and shows server hosts that do not apply.
|
|
31
|
+
...(typeof value?.transport === 'string' && value.transport
|
|
32
|
+
? { transport: value.transport } : {}),
|
|
33
|
+
...(typeof value?.provider === 'string' && value.provider
|
|
34
|
+
? { provider: value.provider } : {}),
|
|
35
|
+
...(text(value?.imapHost) ? { imapHost: text(value.imapHost) } : {}),
|
|
36
|
+
...(Number.isSafeInteger(value?.imapPort) ? { imapPort: value.imapPort } : {}),
|
|
37
|
+
...(text(value?.smtpHost) ? { smtpHost: text(value.smtpHost) } : {}),
|
|
38
|
+
...(Number.isSafeInteger(value?.smtpPort) ? { smtpPort: value.smtpPort } : {}),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function text(value) {
|
|
43
|
+
return typeof value === 'string' && value.trim() ? value.trim() : '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const api = createTokenChannelApi('Email', ' IMAP/SMTP 邮箱', {
|
|
47
|
+
normalizeBotExtension: normalizeEmailBotExtension,
|
|
48
|
+
});
|
|
49
|
+
export { api as emailClientApi };
|
|
50
|
+
export const unwrapRpcResult = api.unwrapRpcResult;
|
|
51
|
+
export const normalizeSnapshot = api.normalizeSnapshot;
|
|
52
|
+
export const presentError = api.presentError;
|