@xmanrui/dsh-im 4.16.1 → 4.17.1
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 +3 -1
- package/README.md +3 -1
- package/lib/client.js +90 -34
- package/lib/index.js +265 -262
- package/package.json +4 -3
- package/plugin-src/client/channels/feishu/api.js +3 -0
- package/plugin-src/client/channels/feishu/index.js +45 -13
- package/plugin-src/client/i18n.js +13 -2
- package/plugin-src/client/index.js +15 -14
- package/plugin-src/host/channels/dingtalk/rpc.mjs +2 -4
- package/plugin-src/host/channels/feishu/production.mjs +1 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +22 -4
- package/plugin-src/host/channels/office/rpc.mjs +2 -1
- package/plugin-src/host/channels/qq/rpc.mjs +2 -4
- package/plugin-src/host/channels/shared/rpc.mjs +2 -4
- package/plugin-src/host/channels/shared/startup.mjs +2 -4
- package/plugin-src/host/channels/slack/rpc.mjs +2 -4
- package/plugin-src/host/channels/telegram/rpc.mjs +2 -4
- package/plugin-src/host/channels/wecom/rpc.mjs +2 -4
- package/plugin-src/host/channels/wecom-app/rpc.mjs +2 -4
- package/plugin-src/host/channels/weixin/rpc.mjs +2 -4
- package/plugin-src/host/channels/whatsapp/rpc.mjs +2 -4
- package/plugin-src/host/delivery-rpc.mjs +2 -4
- package/plugin-src/host/inbound-ttl-rpc.mjs +2 -4
- package/plugin-src/host/index.mjs +1 -1
- package/plugin-src/host/update-rpc.mjs +2 -1
- package/plugin-src/management-rpc.mjs +77 -0
- package/src/channels/feishu/bridge.mjs +475 -11
- package/src/channels/feishu/feishu-cards.mjs +130 -0
- package/src/channels/feishu/feishu-runtime.mjs +10 -0
- package/src/channels/feishu/multi-bot-controller.mjs +28 -0
- package/src/channels/feishu/plugin-config-store.mjs +2 -0
- package/src/channels/feishu/step-push-mode.mjs +19 -0
- package/src/channels/shared/i18n-en/feishu.mjs +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmanrui/dsh-im",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.17.1",
|
|
4
4
|
"description": "把十种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect ten IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -97,12 +97,13 @@
|
|
|
97
97
|
"platform": "web"
|
|
98
98
|
},
|
|
99
99
|
"compatibility": {
|
|
100
|
-
"dsh": "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1",
|
|
100
|
+
"dsh": "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1 || 0.1.5-alpha.1",
|
|
101
101
|
"dshReleases": {
|
|
102
102
|
"0.1.2-alpha.4": "compatible",
|
|
103
103
|
"0.1.2-alpha.5": "compatible",
|
|
104
104
|
"0.1.2-rc.1": "compatible",
|
|
105
|
-
"0.1.3-alpha.1": "compatible"
|
|
105
|
+
"0.1.3-alpha.1": "compatible",
|
|
106
|
+
"0.1.5-alpha.1": "compatible"
|
|
106
107
|
},
|
|
107
108
|
"profiles": [
|
|
108
109
|
"web"
|
|
@@ -11,6 +11,7 @@ import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } fr
|
|
|
11
11
|
import { normalizeLastMessageError } from "../../last-message-error.js";
|
|
12
12
|
import { normalizeAccessPolicy } from "../../../../src/channels/shared/access-policy.mjs";
|
|
13
13
|
import { normalizeContextEnhancementConfig } from "../../../../src/channels/shared/context-enhancement.mjs";
|
|
14
|
+
import { normalizeFeishuStepPushMode } from "../../../../src/channels/feishu/step-push-mode.mjs";
|
|
14
15
|
|
|
15
16
|
export const FEISHU_RPC_CHANNEL = "/feishu";
|
|
16
17
|
|
|
@@ -33,6 +34,7 @@ export const FEISHU_ENDPOINTS = Object.freeze({
|
|
|
33
34
|
setGroupResponseMode: "bot.group-response-mode.set",
|
|
34
35
|
setGroupTopicReply: "bot.group-topic-reply.set",
|
|
35
36
|
setStepPush: "bot.step-push.set",
|
|
37
|
+
setStepPushMode: "bot.step-push-mode.set",
|
|
36
38
|
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
|
|
37
39
|
testConnection: "connection.test",
|
|
38
40
|
disconnect: "connection.disconnect",
|
|
@@ -219,6 +221,7 @@ export function normalizeBotConnection(value, fallbackBotId) {
|
|
|
219
221
|
groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
|
|
220
222
|
groupTopicReply: value.groupTopicReply === true,
|
|
221
223
|
stepPush: value.stepPush === true,
|
|
224
|
+
stepPushMode: normalizeFeishuStepPushMode(value.stepPushMode),
|
|
222
225
|
groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
|
|
223
226
|
bot: normalizeBot(value.bot),
|
|
224
227
|
health: normalizeHealth(value.health, connected),
|
|
@@ -464,21 +464,20 @@ function RemoveConfirmation({ bot, busy, onConfirm, onCancel }) {
|
|
|
464
464
|
);
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
/**
|
|
468
|
-
function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
467
|
+
/** One select for the step-push presentation: off / per-step posts / process card. */
|
|
468
|
+
function StepPushEditor({ value = false, mode = "post", disabled = false, onSave, onModeSave }) {
|
|
469
469
|
const titleId = React.useId();
|
|
470
470
|
const helpId = `${titleId}-help`;
|
|
471
|
-
const current = value === true ?
|
|
471
|
+
const current = value === true ? mode : "off";
|
|
472
472
|
const [saving, setSaving] = React.useState(false);
|
|
473
473
|
const [error, setError] = React.useState(null);
|
|
474
474
|
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
if ((next ? "on" : "off") === current || saving || disabled) return;
|
|
475
|
+
const save = async (run) => {
|
|
476
|
+
if (saving || disabled) return;
|
|
478
477
|
setSaving(true);
|
|
479
478
|
setError(null);
|
|
480
479
|
try {
|
|
481
|
-
await
|
|
480
|
+
await run();
|
|
482
481
|
} catch (cause) {
|
|
483
482
|
setError(cause?.message ?? "分步直推设置保存失败,请重试。");
|
|
484
483
|
} finally {
|
|
@@ -486,13 +485,37 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
486
485
|
}
|
|
487
486
|
};
|
|
488
487
|
|
|
488
|
+
const change = (event) => {
|
|
489
|
+
const next = event.target.value;
|
|
490
|
+
if (next === current) return;
|
|
491
|
+
void save(async () => {
|
|
492
|
+
if (next === "off") {
|
|
493
|
+
// Turning off only needs the flag when it was on.
|
|
494
|
+
if (value === true) await onSave?.(false);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const nextMode = next === "streaming_card" ? "streaming_card" : "post";
|
|
498
|
+
// Enabling (or switching presentation) may need both writes; the flag
|
|
499
|
+
// must land before the mode so the runtime never sees a mode without
|
|
500
|
+
// step push enabled.
|
|
501
|
+
if (value !== true) await onSave?.(true);
|
|
502
|
+
if (nextMode !== mode) await onModeSave?.(nextMode);
|
|
503
|
+
});
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
const helpText = current === "off"
|
|
507
|
+
? "适合日常问答:执行过程中不显示工具调用等中间步骤,只回复最终结果"
|
|
508
|
+
: current === "streaming_card"
|
|
509
|
+
? "推荐长任务使用:过程与最终答案都在同一张卡片里实时更新,不刷屏"
|
|
510
|
+
: "每一步都单独发一条消息(含工具调用和过程说明);注意长任务会连续发送较多消息";
|
|
511
|
+
|
|
489
512
|
return h("section", {
|
|
490
513
|
className: "dim-feishuGroupControl",
|
|
491
514
|
"aria-labelledby": titleId,
|
|
492
515
|
},
|
|
493
516
|
h("div", { className: "dim-feishuGroupControlHeader" },
|
|
494
517
|
h("div", { className: "dim-presetTitle" },
|
|
495
|
-
h("h3", { id: titleId }, "
|
|
518
|
+
h("h3", { id: titleId }, "任务过程展示"),
|
|
496
519
|
h("span", { className: "dim-presetHelp" },
|
|
497
520
|
h("button", {
|
|
498
521
|
type: "button",
|
|
@@ -504,7 +527,7 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
504
527
|
id: helpId,
|
|
505
528
|
className: "dim-presetTooltip",
|
|
506
529
|
role: "tooltip",
|
|
507
|
-
}, "
|
|
530
|
+
}, "设置任务执行过程的呈现方式:不显示、实时卡片或逐步消息"))),
|
|
508
531
|
saving
|
|
509
532
|
? h("span", { className: "dim-feishuGroupControlStatus", role: "status" }, "保存中…")
|
|
510
533
|
: null),
|
|
@@ -512,11 +535,13 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
512
535
|
className: "dim-feishuGroupSelect",
|
|
513
536
|
value: current,
|
|
514
537
|
disabled: disabled || saving,
|
|
515
|
-
"aria-label": "
|
|
516
|
-
onChange:
|
|
538
|
+
"aria-label": "任务过程展示",
|
|
539
|
+
onChange: change,
|
|
517
540
|
},
|
|
518
|
-
h("option", { value: "off" }, "
|
|
519
|
-
h("option", { value: "
|
|
541
|
+
h("option", { value: "off" }, "不显示过程(只发送最终答案)"),
|
|
542
|
+
h("option", { value: "streaming_card" }, "实时过程卡(全程一张卡片动态更新)"),
|
|
543
|
+
h("option", { value: "post" }, "逐步直播(每一步单独发一条消息)")),
|
|
544
|
+
h("p", { className: "dim-feishuGroupHelp" }, helpText),
|
|
520
545
|
error ? h("p", {
|
|
521
546
|
className: "dim-feishuGroupError",
|
|
522
547
|
role: "alert",
|
|
@@ -539,6 +564,7 @@ export function BotCard({
|
|
|
539
564
|
onAgentPresetSave,
|
|
540
565
|
onContextEnhancementSave,
|
|
541
566
|
onStepPushSave,
|
|
567
|
+
onStepPushModeSave,
|
|
542
568
|
onRequestRemove,
|
|
543
569
|
onConfirmRemove,
|
|
544
570
|
onCancelRemove,
|
|
@@ -627,8 +653,10 @@ export function BotCard({
|
|
|
627
653
|
}),
|
|
628
654
|
h(StepPushEditor, {
|
|
629
655
|
value: connection.stepPush,
|
|
656
|
+
mode: connection.stepPushMode,
|
|
630
657
|
disabled: Boolean(busy),
|
|
631
658
|
onSave: onStepPushSave,
|
|
659
|
+
onModeSave: onStepPushModeSave,
|
|
632
660
|
}),
|
|
633
661
|
provisionContent
|
|
634
662
|
? h("section", {
|
|
@@ -723,6 +751,7 @@ function BotList(props) {
|
|
|
723
751
|
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
|
|
724
752
|
onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
|
|
725
753
|
onStepPushSave: (stepPush) => props.onStepPushSave(bot, stepPush),
|
|
754
|
+
onStepPushModeSave: (stepPushMode) => props.onStepPushModeSave(bot, stepPushMode),
|
|
726
755
|
onRequestRemove: () => props.onRequestRemove(bot),
|
|
727
756
|
onConfirmRemove: () => props.onConfirmRemove(bot),
|
|
728
757
|
onCancelRemove: props.onCancelRemove,
|
|
@@ -1500,6 +1529,9 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|
|
1500
1529
|
onStepPushSave: (connection, stepPush) => saveBotSetting(
|
|
1501
1530
|
connection, "step-push", FEISHU_ENDPOINTS.setStepPush, { stepPush },
|
|
1502
1531
|
),
|
|
1532
|
+
onStepPushModeSave: (connection, stepPushMode) => saveBotSetting(
|
|
1533
|
+
connection, "step-push-mode", FEISHU_ENDPOINTS.setStepPushMode, { stepPushMode },
|
|
1534
|
+
),
|
|
1503
1535
|
onRequestRemove: requestRemove,
|
|
1504
1536
|
onConfirmRemove: (bot) => void confirmRemove(bot),
|
|
1505
1537
|
onCancelRemove: cancelRemove,
|
|
@@ -223,9 +223,20 @@ const EN = Object.freeze({
|
|
|
223
223
|
'分步直推': 'Step push',
|
|
224
224
|
'查看分步直推说明': 'View step push help',
|
|
225
225
|
'开启后逐步推送工具调用与过程说明': 'Push tool calls and process notes step by step',
|
|
226
|
-
'
|
|
227
|
-
'
|
|
226
|
+
'任务过程展示': 'Task progress display',
|
|
227
|
+
'设置任务执行过程的呈现方式:不显示、实时卡片或逐步消息': 'Choose how the execution is presented: hidden, one live card, or step-by-step messages',
|
|
228
|
+
'不显示过程(只发送最终答案)': 'Hide the process (send the final answer only)',
|
|
229
|
+
'实时过程卡(全程一张卡片动态更新)': 'Live process card (one card updated throughout)',
|
|
230
|
+
'逐步直播(每一步单独发一条消息)': 'Step-by-step feed (one message per step)',
|
|
231
|
+
'适合日常问答:执行过程中不显示工具调用等中间步骤,只回复最终结果': 'For everyday Q&A: tool calls and other interim steps stay hidden, only the final result is replied',
|
|
232
|
+
'推荐长任务使用:过程与最终答案都在同一张卡片里实时更新,不刷屏': 'Recommended for long tasks: the process and the final answer update live in one card without flooding the chat',
|
|
233
|
+
'每一步都单独发一条消息(含工具调用和过程说明);注意长任务会连续发送较多消息': 'Every step is sent as its own message (including tool calls and notes); long tasks may send many messages in a row',
|
|
228
234
|
'分步直推设置保存失败,请重试。': 'Could not save the step push setting. Try again.',
|
|
235
|
+
'zcode过程卡模式': 'ZCode process-card mode',
|
|
236
|
+
'过程说明、工具摘要与最终答案都在同一张卡片中原地刷新':
|
|
237
|
+
'Process notes, the tool summary, and the final answer refresh in place inside one card',
|
|
238
|
+
'思考与工具摘要折叠展示,最终答案在同一张卡片中原地刷新':
|
|
239
|
+
'Thinking and the tool summary stay folded; the final answer refreshes in place inside one card',
|
|
229
240
|
'钉钉设置': 'DingTalk settings',
|
|
230
241
|
'企业微信设置': 'WeCom settings',
|
|
231
242
|
'扫码接入机器人': 'Scan QR code',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { callManagementRpc } from '../management-rpc.mjs';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
import manifest from '../../package.json' with { type: 'json' };
|
|
3
4
|
|
|
@@ -403,33 +404,33 @@ export function apply(ctx) {
|
|
|
403
404
|
}, 'im-settings: install combined channel styles');
|
|
404
405
|
|
|
405
406
|
const feishuRpcCall = (endpoint, payload, signal) =>
|
|
406
|
-
ctx.connection
|
|
407
|
+
callManagementRpc(ctx.connection, FEISHU_RPC_CHANNEL, endpoint, payload, signal);
|
|
407
408
|
const weixinRpcCall = (endpoint, payload, signal) =>
|
|
408
|
-
ctx.connection
|
|
409
|
+
callManagementRpc(ctx.connection, WEIXIN_RPC_CHANNEL, endpoint, payload, signal);
|
|
409
410
|
const dingtalkRpcCall = (endpoint, payload, signal) =>
|
|
410
|
-
ctx.connection
|
|
411
|
+
callManagementRpc(ctx.connection, DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
|
|
411
412
|
const qqRpcCall = (endpoint, payload, signal) =>
|
|
412
|
-
ctx.connection
|
|
413
|
+
callManagementRpc(ctx.connection, QQ_RPC_CHANNEL, endpoint, payload, signal);
|
|
413
414
|
const wecomRpcCall = (endpoint, payload, signal) =>
|
|
414
|
-
ctx.connection
|
|
415
|
+
callManagementRpc(ctx.connection, WECOM_RPC_CHANNEL, endpoint, payload, signal);
|
|
415
416
|
const wecomAppRpcCall = (endpoint, payload, signal) =>
|
|
416
|
-
ctx.connection
|
|
417
|
+
callManagementRpc(ctx.connection, WECOM_APP_RPC_CHANNEL, endpoint, payload, signal);
|
|
417
418
|
const telegramRpcCall = (endpoint, payload, signal) =>
|
|
418
|
-
ctx.connection
|
|
419
|
+
callManagementRpc(ctx.connection, TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
|
|
419
420
|
const discordRpcCall = (endpoint, payload, signal) =>
|
|
420
|
-
ctx.connection
|
|
421
|
+
callManagementRpc(ctx.connection, DISCORD_RPC_CHANNEL, endpoint, payload, signal);
|
|
421
422
|
const whatsappRpcCall = (endpoint, payload, signal) =>
|
|
422
|
-
ctx.connection
|
|
423
|
+
callManagementRpc(ctx.connection, WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
|
|
423
424
|
const slackRpcCall = (endpoint, payload, signal) =>
|
|
424
|
-
ctx.connection
|
|
425
|
+
callManagementRpc(ctx.connection, SLACK_RPC_CHANNEL, endpoint, payload, signal);
|
|
425
426
|
const officeRpcCall = (endpoint, payload, signal) =>
|
|
426
|
-
ctx.connection
|
|
427
|
+
callManagementRpc(ctx.connection, OFFICE_RPC_CHANNEL, endpoint, payload, signal);
|
|
427
428
|
const updateRpcCall = (endpoint, payload, signal) =>
|
|
428
|
-
ctx.connection
|
|
429
|
+
callManagementRpc(ctx.connection, UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
|
429
430
|
const deliveryRpcCall = (endpoint, payload, signal) =>
|
|
430
|
-
ctx.connection
|
|
431
|
+
callManagementRpc(ctx.connection, DELIVERY_RPC_CHANNEL, endpoint, payload, signal);
|
|
431
432
|
const globalSettingsRpcCall = (endpoint, payload, signal) =>
|
|
432
|
-
ctx.connection
|
|
433
|
+
callManagementRpc(ctx.connection, GLOBAL_SETTINGS_RPC_CHANNEL, endpoint, payload, signal);
|
|
433
434
|
const workspaceDirectoryPicker = Object.freeze({
|
|
434
435
|
listDirectory: (path, signal) =>
|
|
435
436
|
callWorkspaceDirectoryApi(ctx, 'listDirectory', path, signal),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
3
4
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
|
@@ -336,10 +337,7 @@ export function createDingtalkRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
336
337
|
}
|
|
337
338
|
|
|
338
339
|
export function installDingtalkRpc(ctx, controller, options, authority) {
|
|
339
|
-
|
|
340
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
341
|
-
}
|
|
342
|
-
return ctx.connection.rpc.handle(
|
|
340
|
+
return registerManagementRpc(ctx,
|
|
343
341
|
DINGTALK_RPC_CHANNEL,
|
|
344
342
|
createDingtalkRpcHandler(controller, options),
|
|
345
343
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -219,6 +219,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
219
219
|
groupResponseMode: botConfig.groupResponseMode,
|
|
220
220
|
groupTopicReply: botConfig.groupTopicReply,
|
|
221
221
|
stepPush: botConfig.stepPush,
|
|
222
|
+
stepPushMode: botConfig.stepPushMode,
|
|
222
223
|
ownerOpenIds: botConfig.ownerOpenIds ?? [botConfig.ownerOpenId],
|
|
223
224
|
harness: workspaceScope.harness,
|
|
224
225
|
state: workspaceScope.state,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
import {
|
|
3
4
|
normalizeAgentPresetCatalog,
|
|
@@ -21,6 +22,10 @@ import {
|
|
|
21
22
|
isFeishuGroupResponseMode,
|
|
22
23
|
normalizeFeishuGroupResponseMode,
|
|
23
24
|
} from '../../../../src/channels/feishu/group-response-mode.mjs';
|
|
25
|
+
import {
|
|
26
|
+
isFeishuStepPushMode,
|
|
27
|
+
normalizeFeishuStepPushMode,
|
|
28
|
+
} from '../../../../src/channels/feishu/step-push-mode.mjs';
|
|
24
29
|
import {
|
|
25
30
|
FEISHU_ENDPOINTS as FEISHU_CLIENT_ENDPOINTS,
|
|
26
31
|
FEISHU_RPC_CHANNEL,
|
|
@@ -295,6 +300,7 @@ function publicBotEntry(entry) {
|
|
|
295
300
|
groupResponseMode: normalizeFeishuGroupResponseMode(source.groupResponseMode),
|
|
296
301
|
groupTopicReply: source.groupTopicReply === true,
|
|
297
302
|
stepPush: source.stepPush === true,
|
|
303
|
+
stepPushMode: normalizeFeishuStepPushMode(source.stepPushMode),
|
|
298
304
|
groupMessagePermissionGranted: source.groupMessagePermissionGranted === true,
|
|
299
305
|
bot: publicBot(source.bot),
|
|
300
306
|
health: publicHealth(source, connected),
|
|
@@ -466,6 +472,13 @@ function validPayload(endpoint, payload) {
|
|
|
466
472
|
? null
|
|
467
473
|
: '请选择是否分步直推。';
|
|
468
474
|
}
|
|
475
|
+
if (endpoint === FEISHU_ENDPOINTS.setStepPushMode) {
|
|
476
|
+
return hasOnlyKeys(payload, new Set(['botId', 'stepPushMode']))
|
|
477
|
+
&& safeOpaqueId(payload.botId)
|
|
478
|
+
&& isFeishuStepPushMode(payload.stepPushMode)
|
|
479
|
+
? null
|
|
480
|
+
: '请选择分步直推的呈现方式。';
|
|
481
|
+
}
|
|
469
482
|
return 'Unknown Feishu endpoint.';
|
|
470
483
|
}
|
|
471
484
|
|
|
@@ -758,6 +771,14 @@ export function createFeishuRpcHandler(controller, { encodeQr = qrCodeDataUrl }
|
|
|
758
771
|
await controller.updateStepPush(payload.botId, payload.stepPush),
|
|
759
772
|
{ encodeQr: cachedEncodeQr },
|
|
760
773
|
);
|
|
774
|
+
} else if (endpoint === FEISHU_ENDPOINTS.setStepPushMode) {
|
|
775
|
+
if (typeof controller.updateStepPushMode !== 'function') {
|
|
776
|
+
throw new Error('Step push mode update is unavailable');
|
|
777
|
+
}
|
|
778
|
+
value = await toPublicFeishuStatus(
|
|
779
|
+
await controller.updateStepPushMode(payload.botId, payload.stepPushMode),
|
|
780
|
+
{ encodeQr: cachedEncodeQr },
|
|
781
|
+
);
|
|
761
782
|
} else {
|
|
762
783
|
if (typeof controller.deleteBot !== 'function') throw new Error('Multi-bot delete is unavailable');
|
|
763
784
|
value = await toPublicFeishuStatus(await controller.deleteBot(payload.botId), { encodeQr: cachedEncodeQr });
|
|
@@ -775,10 +796,7 @@ export function createFeishuRpcHandler(controller, { encodeQr = qrCodeDataUrl }
|
|
|
775
796
|
|
|
776
797
|
/** Register the `/feishu` logical channel with its configured browser authority. */
|
|
777
798
|
export function installFeishuRpc(ctx, controller, options, authority) {
|
|
778
|
-
|
|
779
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
780
|
-
}
|
|
781
|
-
return ctx.connection.rpc.handle(
|
|
799
|
+
return registerManagementRpc(ctx,
|
|
782
800
|
FEISHU_RPC_CHANNEL,
|
|
783
801
|
createFeishuRpcHandler(controller, options),
|
|
784
802
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
2
3
|
import { OFFICE_RPC_CHANNEL, OFFICE_RPC_ENDPOINTS } from '../../../../src/channels/office/protocol.mjs';
|
|
3
4
|
|
|
@@ -40,7 +41,7 @@ export function createOfficeRpcHandler(controller) {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
export function installOfficeRpc(ctx, controller, authority) {
|
|
43
|
-
return ctx
|
|
44
|
+
return registerManagementRpc(ctx,
|
|
44
45
|
OFFICE_RPC_CHANNEL,
|
|
45
46
|
createOfficeRpcHandler(controller),
|
|
46
47
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
import {
|
|
3
4
|
connectionTestTargetUnavailable,
|
|
@@ -227,10 +228,7 @@ export function createQqRpcHandler(controller, { encodeQr = qrDataUrl } = {}) {
|
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
export function installQqRpc(ctx, controller, options, authority) {
|
|
230
|
-
|
|
231
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
232
|
-
}
|
|
233
|
-
return ctx.connection.rpc.handle(
|
|
231
|
+
return registerManagementRpc(ctx,
|
|
234
232
|
QQ_RPC_CHANNEL,
|
|
235
233
|
createQqRpcHandler(controller, options),
|
|
236
234
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from './context-enhancement-rpc.mjs';
|
|
2
3
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from './access-policy-rpc.mjs';
|
|
3
4
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
@@ -197,10 +198,7 @@ export function createTokenBotRpcHandler(controller, { channel }) {
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
export function installTokenBotRpc(ctx, controller, { channel, rpcChannel, authority }) {
|
|
200
|
-
|
|
201
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
202
|
-
}
|
|
203
|
-
return ctx.connection.rpc.handle(
|
|
201
|
+
return registerManagementRpc(ctx,
|
|
204
202
|
rpcChannel,
|
|
205
203
|
createTokenBotRpcHandler(controller, { channel }),
|
|
206
204
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
2
3
|
import { publicChannelInitializing, publicChannelStartupError } from './startup-error.mjs';
|
|
3
4
|
|
|
@@ -5,12 +6,9 @@ import { publicChannelInitializing, publicChannelStartupError } from './startup-
|
|
|
5
6
|
export async function installProductionChannel(ctx, config, {
|
|
6
7
|
channel, rpcChannel, createProduction, createHandler,
|
|
7
8
|
}) {
|
|
8
|
-
if (!ctx?.connection?.rpc || typeof ctx.connection.rpc.handle !== 'function') {
|
|
9
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
10
|
-
}
|
|
11
9
|
let startupError = publicChannelInitializing(channel);
|
|
12
10
|
let handler = async () => ({ ok: false, error: startupError });
|
|
13
|
-
const disposeRpc = ctx
|
|
11
|
+
const disposeRpc = registerManagementRpc(ctx, rpcChannel, (endpoint, payload, signal) => {
|
|
14
12
|
if (signal?.aborted) {
|
|
15
13
|
return { ok: false, error: { code: 'cancelled', message: 'The request was cancelled.', details: {} } };
|
|
16
14
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
2
3
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
|
3
4
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
@@ -200,10 +201,7 @@ export function createSlackRpcHandler(controller) {
|
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
export function installSlackRpc(ctx, controller, authority) {
|
|
203
|
-
|
|
204
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
205
|
-
}
|
|
206
|
-
return ctx.connection.rpc.handle(
|
|
204
|
+
return registerManagementRpc(ctx,
|
|
207
205
|
SLACK_RPC_CHANNEL,
|
|
208
206
|
createSlackRpcHandler(controller),
|
|
209
207
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import {
|
|
2
3
|
TOKEN_BOT_ENDPOINTS,
|
|
3
4
|
createTokenBotRpcHandler,
|
|
@@ -13,10 +14,7 @@ export function createTelegramRpcHandler(controller) {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export function installTelegramRpc(ctx, controller, authority) {
|
|
16
|
-
|
|
17
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
18
|
-
}
|
|
19
|
-
return ctx.connection.rpc.handle(
|
|
17
|
+
return registerManagementRpc(ctx,
|
|
20
18
|
TELEGRAM_RPC_CHANNEL,
|
|
21
19
|
createTelegramRpcHandler(controller),
|
|
22
20
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
3
4
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
|
@@ -233,10 +234,7 @@ export function installWecomRpc(ctx, controller, options, authority) {
|
|
|
233
234
|
|
|
234
235
|
/** Mount the existing Connection transport before the production controller is ready. */
|
|
235
236
|
export function installWecomRpcHandler(ctx, handler, authority) {
|
|
236
|
-
|
|
237
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
238
|
-
}
|
|
239
|
-
return ctx.connection.rpc.handle(
|
|
237
|
+
return registerManagementRpc(ctx,
|
|
240
238
|
WECOM_RPC_CHANNEL,
|
|
241
239
|
handler,
|
|
242
240
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
2
3
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
|
3
4
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
@@ -214,10 +215,7 @@ export function createWecomAppRpcHandler(controller) {
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
export function installWecomAppRpc(ctx, controller, options, authority) {
|
|
217
|
-
|
|
218
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
219
|
-
}
|
|
220
|
-
return ctx.connection.rpc.handle(
|
|
218
|
+
return registerManagementRpc(ctx,
|
|
221
219
|
WECOM_APP_RPC_CHANNEL,
|
|
222
220
|
createWecomAppRpcHandler(controller, options),
|
|
223
221
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
3
4
|
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
|
@@ -260,10 +261,7 @@ export function createWeixinRpcHandler(controller, { encodeQr = qrDataUrl } = {}
|
|
|
260
261
|
}
|
|
261
262
|
|
|
262
263
|
export function installWeixinRpc(ctx, controller, options, authority) {
|
|
263
|
-
|
|
264
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
265
|
-
}
|
|
266
|
-
return ctx.connection.rpc.handle(
|
|
264
|
+
return registerManagementRpc(ctx,
|
|
267
265
|
WEIXIN_RPC_CHANNEL,
|
|
268
266
|
createWeixinRpcHandler(controller, options),
|
|
269
267
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
1
2
|
import QRCode from 'qrcode';
|
|
2
3
|
|
|
3
4
|
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
|
@@ -218,10 +219,7 @@ export function createWhatsappRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
export function installWhatsappRpc(ctx, controller, options, authority) {
|
|
221
|
-
|
|
222
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
223
|
-
}
|
|
224
|
-
return ctx.connection.rpc.handle(
|
|
222
|
+
return registerManagementRpc(ctx,
|
|
225
223
|
WHATSAPP_RPC_CHANNEL,
|
|
226
224
|
createWhatsappRpcHandler(controller, options),
|
|
227
225
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../management-rpc.mjs';
|
|
1
2
|
import { resolveRpcAuthority } from './rpc-authority.mjs';
|
|
2
3
|
|
|
3
4
|
export const DELIVERY_RPC_CHANNEL = '/dsh-im-delivery';
|
|
@@ -159,10 +160,7 @@ export function createDeliveryRpcHandler(service) {
|
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
export function installDeliveryRpc(ctx, service, { authority } = {}) {
|
|
162
|
-
|
|
163
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
164
|
-
}
|
|
165
|
-
return ctx.connection.rpc.handle(
|
|
163
|
+
return registerManagementRpc(ctx,
|
|
166
164
|
DELIVERY_RPC_CHANNEL,
|
|
167
165
|
createDeliveryRpcHandler(service),
|
|
168
166
|
{ authority: resolveRpcAuthority(authority) },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../management-rpc.mjs';
|
|
1
2
|
import { normalizeInboundTtlHours } from '../../src/channels/shared/inbound-ttl.mjs';
|
|
2
3
|
import { getInboundTtlRuntime } from './inbound-ttl-runtime.mjs';
|
|
3
4
|
|
|
@@ -69,13 +70,10 @@ export function createInboundTtlRpcHandler({ store, service, logger = null } = {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
export function installInboundTtlRpc(ctx, options = {}) {
|
|
72
|
-
if (!ctx?.connection?.rpc || typeof ctx.connection.rpc.handle !== 'function') {
|
|
73
|
-
throw new TypeError('DSH Host Connection RPC is required');
|
|
74
|
-
}
|
|
75
73
|
const runtime = options.runtime ?? getInboundTtlRuntime(ctx, options.config);
|
|
76
74
|
const logger = typeof ctx?.logger === 'function'
|
|
77
75
|
? ctx.logger('dsh-im:inbound-ttl') : (ctx?.logger ?? null);
|
|
78
|
-
return ctx
|
|
76
|
+
return registerManagementRpc(ctx,
|
|
79
77
|
INBOUND_TTL_RPC_CHANNEL,
|
|
80
78
|
createInboundTtlRpcHandler({ ...runtime, logger }),
|
|
81
79
|
{ authority: 'loopback' },
|
|
@@ -130,7 +130,7 @@ export function createImHostPlugin(internals = {}) {
|
|
|
130
130
|
const logger = typeof ctx?.logger === 'function'
|
|
131
131
|
? ctx.logger(name)
|
|
132
132
|
: (ctx?.logger ?? console);
|
|
133
|
-
if (ctx?.connection?.
|
|
133
|
+
if (ctx?.connection?.fetch) {
|
|
134
134
|
try {
|
|
135
135
|
startUpdate(ctx);
|
|
136
136
|
} catch (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerManagementRpc } from '../management-rpc.mjs';
|
|
1
2
|
import { createUpdateRuntime } from './update-runtime.mjs';
|
|
2
3
|
import { createUpdateService } from './update-service.mjs';
|
|
3
4
|
|
|
@@ -42,7 +43,7 @@ export function createUpdateRpcHandler(service) {
|
|
|
42
43
|
export function installUpdateRpc(ctx, options = {}) {
|
|
43
44
|
const runtime = options.runtime ?? createUpdateRuntime({ ctx, moduleUrl: import.meta.url });
|
|
44
45
|
const service = options.service ?? createUpdateService({ runtime });
|
|
45
|
-
const dispose = ctx
|
|
46
|
+
const dispose = registerManagementRpc(ctx, UPDATE_RPC_CHANNEL, createUpdateRpcHandler(service), {
|
|
46
47
|
authority: 'loopback',
|
|
47
48
|
});
|
|
48
49
|
ctx.effect(() => () => service.close(), 'dsh-im: close update installer');
|