feat: add message source context enhancement

This commit is contained in:
xmanrui 2026-08-29 10:46:06 +08:00
parent 5928b33057
commit 0cb79f74e9
69 changed files with 6217 additions and 597 deletions

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
export const DINGTALK_RPC_CHANNEL = '/dingtalk';
@ -13,6 +14,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
deleteBot: 'bot.delete',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
@ -162,6 +164,7 @@ function normalizeBot(value) {
configured: value.configured !== false,
workspace: optionalString(value.workspace, 4_096) ?? '',
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
bot: {
name: optionalString(bot.name, 100) ?? '钉钉机器人',
clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? '已安全保存',

View file

@ -3,6 +3,7 @@ import * as React from 'react';
import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
import { h } from '../../i18n.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -220,6 +221,7 @@ export function AccountCard({
onReconnect,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onRequestRemove,
onConfirmRemove,
onCancelRemove,
@ -254,6 +256,11 @@ export function AccountCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h('div', { className: 'ddt-accountFooter dim-cardFooter' },
h('div', { className: 'dim-cardFooterLayout' },
h('div', { className: 'ddt-actions dim-cardActions' },
@ -294,6 +301,7 @@ function AccountList(props) {
onReconnect: () => props.onReconnect(account),
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
onRequestRemove: () => props.onRequestRemove(account),
onConfirmRemove: () => props.onConfirmRemove(account),
onCancelRemove: props.onCancelRemove,
@ -737,13 +745,13 @@ export function DingtalkSettingsTab({ rpcCall }) {
}
}, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
const saveAgentPreset = React.useCallback(async (account, agentPreset) => {
const saveBotSetting = React.useCallback(async (account, operation, endpoint, payload) => {
const snapshotVersion = workspaceFence.beginMutation();
setBotBusy(account.botId, 'preset');
setBotBusy(account.botId, operation);
try {
const snapshot = normalizeSnapshot(await invoke(
DINGTALK_ENDPOINTS.setAgentPreset,
{ botId: account.botId, agentPreset },
endpoint,
{ botId: account.botId, ...payload },
));
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
setModel({
@ -853,7 +861,12 @@ export function DingtalkSettingsTab({ rpcCall }) {
removeTarget,
onReconnect: (account) => void reconnect(account),
onWorkspaceSave: saveWorkspace,
onAgentPresetSave: saveAgentPreset,
onAgentPresetSave: (account, agentPreset) => saveBotSetting(
account, 'preset', DINGTALK_ENDPOINTS.setAgentPreset, { agentPreset },
),
onContextEnhancementSave: (account, config) => saveBotSetting(
account, 'context-enhancement', DINGTALK_ENDPOINTS.setContextEnhancement, { config },
),
onRequestRemove: (account) => setRemoveTarget(account.botId),
onConfirmRemove: (account) => void remove(account),
onCancelRemove: () => setRemoveTarget(null),

View file

@ -8,6 +8,7 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId } from "../../agent-preset.js";
import { normalizeLastMessageError } from "../../last-message-error.js";
import { normalizeContextEnhancementConfig } from "../../../../src/channels/shared/context-enhancement.mjs";
export const FEISHU_RPC_CHANNEL = "/feishu";
@ -24,6 +25,7 @@ export const FEISHU_ENDPOINTS = Object.freeze({
deleteBot: "bot.delete",
setWorkspace: "bot.workspace.set",
setAgentPreset: "bot.preset.set",
setContextEnhancement: "bot.context-enhancement.set",
setGroupResponseMode: "bot.group-response-mode.set",
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
testConnection: "connection.test",
@ -203,6 +205,7 @@ export function normalizeBotConnection(value, fallbackBotId) {
configured: value.configured !== false,
workspace: optionalString(value.workspace)?.slice(0, 4_096) ?? "",
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
bot: normalizeBot(value.bot),

View file

@ -16,6 +16,7 @@ import {
} from "./api.js";
import { useAnimationFrameScheduler } from "../../lifecycle.js";
import { WorkspaceEditor } from "../../workspace-editor.js";
import { ContextEnhancementEditor } from "../../context-enhancement.js";
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -553,6 +554,7 @@ export function BotCard({
onRepairCallback,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onGroupResponseModeSave,
onGroupMessagePermissionAuthorize,
onRequestRemove,
@ -611,6 +613,11 @@ export function BotCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: connection.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h(GroupResponseModeEditor, {
value: connection.groupResponseMode,
permissionGranted: connection.groupMessagePermissionGranted,
@ -708,6 +715,7 @@ function BotList(props) {
onRepairCallback: () => props.onRepairCallback(bot),
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
onGroupResponseModeSave: (groupResponseMode) => props.onGroupResponseModeSave(bot, groupResponseMode),
onGroupMessagePermissionAuthorize: () => props.onGroupMessagePermissionAuthorize(bot),
onRequestRemove: () => props.onRequestRemove(bot),
@ -1296,15 +1304,15 @@ export function FeishuSettingsTab({ rpcCall }) {
}
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
const saveAgentPreset = React.useCallback(async (connection, agentPreset) => {
const saveBotSetting = React.useCallback(async (connection, operation, endpoint, payload) => {
const { botId } = connection;
const snapshotVersion = workspaceFence.beginMutation();
setBotBusy(botId, "preset");
setBotBusy(botId, operation);
setBotError(botId, null);
try {
const snapshot = normalizeBotsSnapshot(await invoke(
FEISHU_ENDPOINTS.setAgentPreset,
{ botId, agentPreset },
endpoint,
{ botId, ...payload },
));
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
mergeSnapshot(snapshot);
@ -1521,7 +1529,12 @@ export function FeishuSettingsTab({ rpcCall }) {
onReconnect: (bot) => void reconnectOneBot(bot),
onRepairCallback: repairCallback,
onWorkspaceSave: saveWorkspace,
onAgentPresetSave: saveAgentPreset,
onAgentPresetSave: (connection, agentPreset) => saveBotSetting(
connection, "preset", FEISHU_ENDPOINTS.setAgentPreset, { agentPreset },
),
onContextEnhancementSave: (connection, config) => saveBotSetting(
connection, "context-enhancement", FEISHU_ENDPOINTS.setContextEnhancement, { config },
),
onGroupResponseModeSave: saveGroupResponseMode,
onGroupMessagePermissionAuthorize: authorizeGroupMessages,
onRequestRemove: requestRemove,

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
export const QQ_RPC_CHANNEL = '/qq';
@ -13,6 +14,7 @@ export const QQ_ENDPOINTS = Object.freeze({
deleteBot: 'bot.delete',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
const PROVISION_STATES = new Set(['starting', 'pending', 'refreshing', 'connecting', 'connected', 'failed', 'cancelled']);
@ -87,6 +89,7 @@ function normalizeBot(value) {
state: connected ? 'connected' : state,
workspace: text(value.workspace, '', 4_096),
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
bot: {
name: text(value.bot?.name, 'QQ机器人', 100),
appIdMasked: text(value.bot?.appIdMasked, '应用标识已安全保存', 140),

View file

@ -4,6 +4,7 @@ import { QqLogoGlyph } from '../../channel-logos.js';
import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
import { h } from '../../i18n.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -166,6 +167,7 @@ export function AccountCard({
onReconnect,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onRequestRemove,
onConfirmRemove,
onCancelRemove,
@ -198,6 +200,11 @@ export function AccountCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h('div', { className: 'ddt-accountFooter dim-cardFooter' },
h('div', { className: 'dim-cardFooterLayout' },
h('div', { className: 'ddt-actions dim-cardActions' },
@ -468,6 +475,12 @@ export function QqSettingsTab({ rpcCall }) {
QQ_ENDPOINTS.setAgentPreset,
{ botId: account.botId, agentPreset },
),
onContextEnhancementSave: (config) => botAction(
account,
'context-enhancement',
QQ_ENDPOINTS.setContextEnhancement,
{ botId: account.botId, config },
),
onRequestRemove: () => setRemoveTarget(account.botId),
onCancelRemove: () => setRemoveTarget(null),
onConfirmRemove: async () => {

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
@ -29,6 +30,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
deleteBot: 'bot.delete',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
export function createTokenChannelApi(channel, connectionSummary, {
@ -57,6 +59,7 @@ export function createTokenChannelApi(channel, connectionSummary, {
state: connected ? 'connected' : state,
workspace: text(value.workspace, '', 4_096),
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
bot: {
name: text(value.bot?.name, `${channel}机器人`, 100),
username: text(value.bot?.username, '', 100),

View file

@ -4,6 +4,7 @@ import { CredentialActionIcon, CredentialBindingPanel } from '../../credential-b
import { h } from '../../i18n.js';
import { installDingtalkStyles } from '../dingtalk/styles.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -73,7 +74,7 @@ export function createTokenChannelSettings(definition) {
accountSettingsEndpoint = null,
} = definition;
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
const state = busy === 'reconnect' ? 'connecting' : account.state;
const tone = account.connected ? 'success' : state === 'error' ? 'error' : 'warning';
const stateLabel = account.connected ? '运行正常' : state === 'connecting' ? '正在连接' : '连接未就绪';
@ -105,6 +106,11 @@ export function createTokenChannelSettings(definition) {
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
AccountSettings ? h(AccountSettings, {
account,
busy: Boolean(busy),
@ -309,6 +315,12 @@ export function createTokenChannelSettings(definition) {
endpoints.setAgentPreset,
{ botId: account.botId, agentPreset },
),
onContextEnhancementSave: (config) => botAction(
account,
'context-enhancement',
endpoints.setContextEnhancement,
{ botId: account.botId, config },
),
onAccountSettingsSave: AccountSettings && accountSettingsEndpoint
? (payload) => botAction(
account,

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
export const WECOM_RPC_CHANNEL = '/wecom';
@ -13,6 +14,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
deleteBot: 'bot.delete',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
const PROVISION_STATES = new Set(['starting', 'pending', 'refreshing', 'connecting', 'connected', 'failed', 'cancelled']);
@ -96,6 +98,7 @@ function normalizeBot(value) {
state: connected ? 'connected' : state,
workspace: text(value.workspace, '', 4_096),
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
bot: {
name: text(value.bot?.name, '企业微信机器人', 100),
appIdMasked: text(value.bot?.appIdMasked, '应用标识已安全保存', 140),

View file

@ -4,6 +4,7 @@ import { WecomLogoGlyph } from '../../channel-logos.js';
import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
import { h } from '../../i18n.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -165,6 +166,7 @@ export function AccountCard({
onReconnect,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onRequestRemove,
onConfirmRemove,
onCancelRemove,
@ -197,6 +199,11 @@ export function AccountCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h('div', { className: 'ddt-accountFooter dim-cardFooter' },
h('div', { className: 'dim-cardFooterLayout' },
h('div', { className: 'ddt-actions dim-cardActions' },
@ -499,6 +506,12 @@ export function WecomSettingsTab({ rpcCall }) {
WECOM_ENDPOINTS.setAgentPreset,
{ botId: account.botId, agentPreset },
),
onContextEnhancementSave: (config) => botAction(
account,
'context-enhancement',
WECOM_ENDPOINTS.setContextEnhancement,
{ botId: account.botId, config },
),
onRequestRemove: () => setRemoveTarget(account.botId),
onCancelRemove: () => setRemoveTarget(null),
onConfirmRemove: async () => {

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
export const WEIXIN_RPC_CHANNEL = '/weixin';
export const WEIXIN_ENDPOINTS = Object.freeze({
@ -12,6 +13,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
deleteBot: 'bot.delete',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
@ -121,6 +123,7 @@ function normalizeBot(value) {
configured: value.configured === true,
workspace: string(value.workspace).slice(0, 4_096),
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
bot: {
name: string(value.bot.name, '微信机器人'),
accountIdMasked: string(value.bot.accountIdMasked, '已安全保存'),

View file

@ -15,6 +15,7 @@ import {
} from './api.js';
import { createPollScheduler, useAnimationFrameScheduler } from '../../lifecycle.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -207,6 +208,7 @@ export function AccountCard({
onReconnect,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onRequestRemove,
onConfirmRemove,
onCancelRemove,
@ -238,6 +240,12 @@ export function AccountCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
groupSupported: false,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h('div', { className: 'dxw-accountFooter dim-cardFooter' },
h('div', { className: 'dim-cardFooterLayout' },
h('div', { className: 'dxw-actions dim-cardActions' },
@ -280,6 +288,7 @@ function AccountList(props) {
onReconnect: () => props.onReconnect(account),
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
onRequestRemove: () => props.onRequestRemove(account),
onConfirmRemove: () => props.onConfirmRemove(account),
onCancelRemove: props.onCancelRemove,
@ -594,13 +603,13 @@ export function WeixinSettingsTab({ rpcCall }) {
}
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
const saveAgentPreset = React.useCallback(async (account, agentPreset) => {
const saveBotSetting = React.useCallback(async (account, operation, endpoint, payload) => {
const snapshotVersion = workspaceFence.beginMutation();
setBotBusy(account.botId, 'preset');
setBotBusy(account.botId, operation);
try {
const snapshot = normalizeSnapshot(await invoke(
WEIXIN_ENDPOINTS.setAgentPreset,
{ botId: account.botId, agentPreset },
endpoint,
{ botId: account.botId, ...payload },
));
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
setModel({
@ -703,7 +712,12 @@ export function WeixinSettingsTab({ rpcCall }) {
removeTarget,
onReconnect: (account) => void reconnect(account),
onWorkspaceSave: saveWorkspace,
onAgentPresetSave: saveAgentPreset,
onAgentPresetSave: (account, agentPreset) => saveBotSetting(
account, 'preset', WEIXIN_ENDPOINTS.setAgentPreset, { agentPreset },
),
onContextEnhancementSave: (account, config) => saveBotSetting(
account, 'context-enhancement', WEIXIN_ENDPOINTS.setContextEnhancement, { config },
),
onRequestRemove: (account) => setRemoveTarget(account.botId),
onConfirmRemove: (account) => void remove(account),
onCancelRemove: () => setRemoveTarget(null),

View file

@ -1,5 +1,6 @@
import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
import { normalizeLastMessageError } from '../../last-message-error.js';
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
export const WHATSAPP_RPC_CHANNEL = '/whatsapp';
@ -13,6 +14,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
setAccessPolicy: 'bot.access-policy.set',
setWorkspace: 'bot.workspace.set',
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
setContextEnhancement: 'bot.context-enhancement.set',
});
const PROVISION_STATES = new Set(['starting', 'pending', 'connecting', 'connected', 'failed', 'cancelled']);
@ -88,6 +90,7 @@ function normalizeBot(value) {
state: connected ? 'connected' : state,
workspace: text(value.workspace, '', 4_096),
agentPreset: normalizeAgentPresetId(value.agentPreset),
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
accessPolicy: {
accessMode: ['self-only', 'private-allowlist', 'open'].includes(
value.accessPolicy?.accessMode,

View file

@ -4,6 +4,7 @@ import { WhatsappLogoGlyph } from '../../channel-logos.js';
import { QrActionIcon } from '../../credential-binding.js';
import { h } from '../../i18n.js';
import { WorkspaceEditor } from '../../workspace-editor.js';
import { ContextEnhancementEditor } from '../../context-enhancement.js';
import {
AgentPresetCatalogContext,
AgentPresetEditor,
@ -297,6 +298,7 @@ export function WhatsappAccountCard({
onReconnect,
onWorkspaceSave,
onAgentPresetSave,
onContextEnhancementSave,
onAccessPolicySave,
onRequestRemove,
onConfirmRemove,
@ -334,6 +336,11 @@ export function WhatsappAccountCard({
disabled: Boolean(busy),
onSave: onAgentPresetSave,
}),
h(ContextEnhancementEditor, {
config: account.contextEnhancement,
disabled: Boolean(busy),
onSave: onContextEnhancementSave,
}),
h(WhatsappAccessSettings, {
account,
busy: Boolean(busy),
@ -596,6 +603,12 @@ export function WhatsappSettingsTab({ rpcCall }) {
WHATSAPP_ENDPOINTS.setAgentPreset,
{ botId: account.botId, agentPreset },
),
onContextEnhancementSave: (config) => botAction(
account,
'context-enhancement',
WHATSAPP_ENDPOINTS.setContextEnhancement,
{ botId: account.botId, config },
),
onAccessPolicySave: (accessPolicy) => botAction(
account,
'access',