mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 00:33:20 +08:00
Add configurable group session scope (default user_in_chat).
Ops bots now isolate per-speaker Harness sessions in groups, with a settings/RPC toggle to restore shared chat sessions when needed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d10a941fc8
commit
7f1b9bd480
30 changed files with 798 additions and 282 deletions
|
|
@ -5,9 +5,15 @@ import {
|
|||
normalizeAccessPolicy,
|
||||
validateAccessPolicy,
|
||||
} from '../../src/channels/shared/access-policy.mjs';
|
||||
import {
|
||||
DEFAULT_GROUP_SESSION_SCOPE,
|
||||
normalizeGroupSessionScope,
|
||||
validateGroupSessionScope,
|
||||
} from '../../src/channels/shared/session-scope.mjs';
|
||||
import { h, localizeText } from './i18n.js';
|
||||
|
||||
export const ACCESS_POLICY_ENDPOINT = 'bot.access-policy.set';
|
||||
export const GROUP_SESSION_SCOPE_ENDPOINT = 'bot.group-session-scope.set';
|
||||
|
||||
export const ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
||||
weixin: Object.freeze({
|
||||
|
|
@ -262,16 +268,19 @@ export function AccessPolicySettingsPage({ channel, account, rpcCall, onSaved })
|
|||
const definition = ACCESS_CHANNEL_DEFINITIONS[channel];
|
||||
const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
|
||||
const initialKey = JSON.stringify(initialPolicy);
|
||||
const initialScope = normalizeGroupSessionScope(account?.groupSessionScope);
|
||||
const [draft, setDraft] = React.useState(() => clonePolicy(
|
||||
initialPolicy ?? DEFAULT_ACCESS_POLICY,
|
||||
));
|
||||
const [groupSessionScope, setGroupSessionScope] = React.useState(initialScope);
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
const [feedback, setFeedback] = React.useState(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
const next = normalizeAccessPolicy(account?.accessPolicy);
|
||||
setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
|
||||
}, [account?.botId, initialKey]);
|
||||
setGroupSessionScope(normalizeGroupSessionScope(account?.groupSessionScope));
|
||||
}, [account?.botId, initialKey, account?.groupSessionScope]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setFeedback(null);
|
||||
|
|
@ -288,16 +297,27 @@ export function AccessPolicySettingsPage({ channel, account, rpcCall, onSaved })
|
|||
setSaving(true);
|
||||
try {
|
||||
const policy = validateAccessPolicy(draft);
|
||||
const scope = validateGroupSessionScope(groupSessionScope);
|
||||
if (typeof rpcCall !== 'function') throw new Error('访问设置暂不可用。');
|
||||
const value = unwrapRpcResult(await rpcCall(ACCESS_POLICY_ENDPOINT, {
|
||||
botId: account.botId,
|
||||
policy,
|
||||
}));
|
||||
const scopeValue = unwrapRpcResult(await rpcCall(GROUP_SESSION_SCOPE_ENDPOINT, {
|
||||
botId: account.botId,
|
||||
groupSessionScope: scope,
|
||||
}));
|
||||
const saved = policyFromSnapshot(value, account.botId);
|
||||
if (!saved) throw new Error('服务没有返回已保存的访问策略,请刷新后重试。');
|
||||
const savedScope = normalizeGroupSessionScope(
|
||||
scopeValue?.snapshot?.bots?.find?.((bot) => bot?.botId === account.botId)?.groupSessionScope
|
||||
?? scopeValue?.bots?.find?.((bot) => bot?.botId === account.botId)?.groupSessionScope
|
||||
?? scope,
|
||||
);
|
||||
setDraft(clonePolicy(saved));
|
||||
onSaved?.(saved);
|
||||
setFeedback({ tone: 'success', message: '访问设置已保存。' });
|
||||
setGroupSessionScope(savedScope);
|
||||
onSaved?.({ ...saved, groupSessionScope: savedScope });
|
||||
setFeedback({ tone: 'success', message: '访问与群会话设置已保存。' });
|
||||
} catch (error) {
|
||||
setFeedback({
|
||||
tone: 'error',
|
||||
|
|
@ -335,6 +355,40 @@ export function AccessPolicySettingsPage({ channel, account, rpcCall, onSaved })
|
|||
unsupported: definition.groupSupported === false,
|
||||
onChange: (group) => { setDraft((current) => ({ ...current, group })); setFeedback(null); },
|
||||
}),
|
||||
definition.groupSupported === false
|
||||
? null
|
||||
: h('fieldset', {
|
||||
className: 'dim-accessScene',
|
||||
disabled: saving,
|
||||
'data-scene': 'group-session',
|
||||
'aria-label': localizeText('群会话策略'),
|
||||
},
|
||||
h('legend', null,
|
||||
h('span', { className: 'dim-accessLegendContent' },
|
||||
h('span', null, '群会话策略'),
|
||||
h('span', { className: 'dim-channelHelp dim-accessLegendHelp' },
|
||||
h('button', {
|
||||
type: 'button',
|
||||
className: 'dim-channelHelpButton',
|
||||
'aria-label': localizeText('查看群会话策略说明'),
|
||||
}, h('span', { 'aria-hidden': true }, '?')),
|
||||
h('span', {
|
||||
className: 'dim-channelTooltip dim-accessHelpTooltip',
|
||||
role: 'tooltip',
|
||||
}, '运维默认按发言人拆分 Session,避免同群多人互相打断;可选改回整群共享 Session。')))),
|
||||
h('div', { className: 'dim-accessControls' },
|
||||
h('label', { className: 'dim-accessField' },
|
||||
h('span', null, '群内 Session 绑定'),
|
||||
h('select', {
|
||||
value: groupSessionScope || DEFAULT_GROUP_SESSION_SCOPE,
|
||||
'aria-label': localizeText('群内 Session 绑定'),
|
||||
onChange: (event) => {
|
||||
setGroupSessionScope(event.target.value);
|
||||
setFeedback(null);
|
||||
},
|
||||
},
|
||||
h('option', { value: 'user_in_chat' }, '按发言人拆分(推荐)'),
|
||||
h('option', { value: 'chat' }, '整群共享一个 Session'))))),
|
||||
feedback ? h('p', {
|
||||
className: 'dim-accessFeedback',
|
||||
'data-tone': feedback.tone,
|
||||
|
|
@ -347,5 +401,5 @@ export function AccessPolicySettingsPage({ channel, account, rpcCall, onSaved })
|
|||
className: 'dim-deliveryButton',
|
||||
'data-kind': 'primary',
|
||||
disabled: saving || !initialPolicy,
|
||||
}, saving ? '正在保存…' : '保存访问设置')));
|
||||
}, saving ? '正在保存…' : '保存访问与会话设置')));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'dingtalk', config: botConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
maxMessageChars: config.maxMessageChars ?? 4_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 15_000,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QRCode from 'qrcode';
|
||||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
||||
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
||||
|
|
@ -22,6 +23,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
approveSender: 'bot.sender.approve',
|
||||
revokeSender: 'bot.sender.revoke',
|
||||
});
|
||||
|
|
@ -106,6 +108,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === DINGTALK_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
if (endpoint === DINGTALK_ENDPOINTS.approveSender) {
|
||||
return exactKeys(payload, ['botId', 'requestId', 'confirm'])
|
||||
&& validId(payload.botId)
|
||||
|
|
@ -294,6 +300,11 @@ export function createDingtalkRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|||
value = await controller.updateAccessPolicy(
|
||||
payload.botId, payload.policy, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === DINGTALK_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId, payload.groupSessionScope, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === DINGTALK_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await publicStatus(
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, id, {
|
||||
channel: 'feishu', config: botConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(id) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
slashCommands: config.slashCommands !== false,
|
||||
...(wsAgent ? { wsAgent } : {}),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { publicWorkspaceError, validWorkspacePayload } from '../shared/workspace
|
|||
import { validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
||||
import { validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
||||
import {
|
||||
isFeishuGroupResponseMode,
|
||||
|
|
@ -24,6 +25,7 @@ import {
|
|||
export const FEISHU_ENDPOINTS = Object.freeze({
|
||||
...FEISHU_CLIENT_ENDPOINTS,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
export { FEISHU_RPC_CHANNEL };
|
||||
export const FEISHU_MULTI_ENDPOINTS = Object.freeze({
|
||||
|
|
@ -433,6 +435,10 @@ function validPayload(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === FEISHU_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
if (endpoint === FEISHU_ENDPOINTS.setGroupResponseMode) {
|
||||
return hasOnlyKeys(payload, new Set(['botId', 'groupResponseMode']))
|
||||
&& safeOpaqueId(payload.botId)
|
||||
|
|
@ -696,6 +702,11 @@ export function createFeishuRpcHandler(controller, { encodeQr = qrCodeDataUrl }
|
|||
payload.botId, payload.policy,
|
||||
(status) => toPublicFeishuStatus(status, { encodeQr: cachedEncodeQr }),
|
||||
);
|
||||
} else if (endpoint === FEISHU_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId, payload.groupSessionScope, (status) => toPublicFeishuStatus(status, { encodeQr: cachedEncodeQr }),
|
||||
);
|
||||
} else if (endpoint === FEISHU_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await toPublicFeishuStatus(
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'qq', config: botConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
||||
logger: {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
} from '../../../../src/channels/shared/connection-test.mjs';
|
||||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
||||
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
||||
|
|
@ -22,6 +23,7 @@ export const QQ_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
export const QQ_RPC_ENDPOINTS = Object.freeze(Object.values(QQ_ENDPOINTS));
|
||||
|
||||
|
|
@ -88,6 +90,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === QQ_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
return 'Unknown QQ endpoint.';
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +199,11 @@ export function createQqRpcHandler(controller, { encodeQr = qrDataUrl } = {}) {
|
|||
value = await controller.updateAccessPolicy(
|
||||
payload.botId, payload.policy, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === QQ_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId, payload.groupSessionScope, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === QQ_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await publicStatus(
|
||||
|
|
|
|||
17
plugin-src/host/channels/shared/group-session-scope-rpc.mjs
Normal file
17
plugin-src/host/channels/shared/group-session-scope-rpc.mjs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { validateGroupSessionScope } from '../../../../src/channels/shared/session-scope.mjs';
|
||||
|
||||
export const SET_GROUP_SESSION_SCOPE_ENDPOINT = 'bot.group-session-scope.set';
|
||||
|
||||
export function validGroupSessionScopePayload(payload) {
|
||||
try {
|
||||
if (!payload || typeof payload !== 'object' || Array.isArray(payload)
|
||||
|| Reflect.ownKeys(payload).length !== 2
|
||||
|| !Object.hasOwn(payload, 'botId') || !Object.hasOwn(payload, 'groupSessionScope')
|
||||
|| typeof payload.botId !== 'string'
|
||||
|| !/^[A-Za-z0-9_-]{1,128}$/.test(payload.botId)) return false;
|
||||
validateGroupSessionScope(payload.groupSessionScope);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -121,6 +121,7 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|||
state: workspaceScope.state,
|
||||
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
||||
accessPolicy: accessPolicyProvider(workspaces, botId, { channel, config: botConfig }),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
||||
logger: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from './context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from './access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from './group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
||||
import {
|
||||
|
|
@ -21,6 +22,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
|
||||
const ENDPOINTS = Object.freeze(Object.values(TOKEN_BOT_ENDPOINTS));
|
||||
|
|
@ -83,6 +85,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === TOKEN_BOT_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
return 'Unknown bot endpoint.';
|
||||
}
|
||||
|
||||
|
|
@ -170,6 +176,9 @@ export function createTokenBotRpcHandler(controller, { channel }) {
|
|||
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setAccessPolicy) {
|
||||
if (typeof controller.updateAccessPolicy !== 'function') throw new Error('Access policy update is unavailable');
|
||||
value = await controller.updateAccessPolicy(payload.botId, payload.policy);
|
||||
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(payload.botId, payload.groupSessionScope);
|
||||
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'slack', config: botConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
||||
logger: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
||||
import {
|
||||
|
|
@ -22,6 +23,7 @@ export const SLACK_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
export const SLACK_RPC_ENDPOINTS = Object.freeze(Object.values(SLACK_ENDPOINTS));
|
||||
|
||||
|
|
@ -87,6 +89,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === SLACK_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
return 'Unknown Slack endpoint.';
|
||||
}
|
||||
|
||||
|
|
@ -174,6 +180,10 @@ export function createSlackRpcHandler(controller) {
|
|||
if (typeof controller.updateAccessPolicy !== 'function') throw new Error('Access policy update is unavailable');
|
||||
value = await controller.updateAccessPolicy(payload.botId, payload.policy);
|
||||
}
|
||||
else if (endpoint === SLACK_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(payload.botId, payload.groupSessionScope);
|
||||
}
|
||||
else if (endpoint === SLACK_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'wecom', config: botConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
||||
maxReconnectAttempts: config.maxReconnectAttempts ?? 10,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QRCode from 'qrcode';
|
||||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
||||
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
||||
|
|
@ -22,6 +23,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
export const WECOM_RPC_ENDPOINTS = Object.freeze(Object.values(WECOM_ENDPOINTS));
|
||||
|
||||
|
|
@ -88,6 +90,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === WECOM_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
return 'Unknown Enterprise WeChat endpoint.';
|
||||
}
|
||||
|
||||
|
|
@ -194,6 +200,11 @@ export function createWecomRpcHandler(controller, { encodeQr = qrDataUrl } = {})
|
|||
value = await controller.updateAccessPolicy(
|
||||
payload.botId, payload.policy, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === WECOM_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId, payload.groupSessionScope, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === WECOM_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await publicStatus(
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'weixin', config: accountConfig,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
maxMessageChars: config.maxMessageChars ?? DEFAULT_WEIXIN_MAX_MESSAGE_CHARS,
|
||||
logger: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QRCode from 'qrcode';
|
||||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import {
|
||||
publicWorkspaceError,
|
||||
|
|
@ -29,6 +30,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
|
|||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
});
|
||||
export const WEIXIN_RPC_ENDPOINTS = Object.freeze(Object.values(WEIXIN_ENDPOINTS));
|
||||
|
||||
|
|
@ -95,6 +97,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === WEIXIN_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
return 'Unknown Weixin endpoint.';
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +235,11 @@ export function createWeixinRpcHandler(controller, { encodeQr = qrDataUrl } = {}
|
|||
value = await controller.updateAccessPolicy(
|
||||
payload.botId, payload.policy, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === WEIXIN_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId, payload.groupSessionScope, (status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === WEIXIN_ENDPOINTS.setAgentPreset) {
|
||||
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
||||
value = await publicStatus(
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|||
accessPolicy: accessPolicyProvider(workspaces, botId, {
|
||||
channel: 'whatsapp', config: botConfig, equals: whatsappAccessPolicyIdsEqual,
|
||||
}),
|
||||
groupSessionScope: { getScope: () => workspaces.groupSessionScopeFor(botId) },
|
||||
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
||||
connectTimeoutMs: config.connectTimeoutMs ?? 30_000,
|
||||
createSession,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import QRCode from 'qrcode';
|
|||
|
||||
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
||||
import { SET_ACCESS_POLICY_ENDPOINT, validAccessPolicyPayload } from '../shared/access-policy-rpc.mjs';
|
||||
import { SET_GROUP_SESSION_SCOPE_ENDPOINT, validGroupSessionScopePayload } from '../shared/group-session-scope-rpc.mjs';
|
||||
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
||||
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
||||
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
||||
|
|
@ -16,6 +17,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|||
reconnectBot: 'bot.reconnect',
|
||||
deleteBot: 'bot.delete',
|
||||
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
||||
setGroupSessionScope: SET_GROUP_SESSION_SCOPE_ENDPOINT,
|
||||
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
||||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
||||
|
|
@ -58,6 +60,10 @@ function payloadFailure(endpoint, payload) {
|
|||
return validAccessPolicyPayload(payload)
|
||||
? null : '请提交有效的访问设置。';
|
||||
}
|
||||
if (endpoint === WHATSAPP_ENDPOINTS.setGroupSessionScope) {
|
||||
return validGroupSessionScopePayload(payload)
|
||||
? null : '请提交有效的群会话策略。';
|
||||
}
|
||||
if (endpoint === WHATSAPP_ENDPOINTS.setWorkspace) {
|
||||
return validWorkspacePayload(payload)
|
||||
? null : '请输入工作区绝对路径。';
|
||||
|
|
@ -190,6 +196,13 @@ export function createWhatsappRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|||
payload.policy,
|
||||
(status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else if (endpoint === WHATSAPP_ENDPOINTS.setGroupSessionScope) {
|
||||
if (typeof controller.updateGroupSessionScope !== 'function') throw new Error('Group session scope update is unavailable');
|
||||
value = await controller.updateGroupSessionScope(
|
||||
payload.botId,
|
||||
payload.groupSessionScope,
|
||||
(status) => publicStatus(status, cachedEncode),
|
||||
);
|
||||
} else {
|
||||
value = await publicStatus(await controller.deleteBot(payload.botId), cachedEncode);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue