mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 05:20:46 +08:00
feat: 按机器人选择 Agent Preset
在九个渠道的设置页卡片上选择 Host 已有预设;未选则跟随默认,只影响之后新建的会话。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c3b3a29f27
commit
3161816cc4
51 changed files with 2227 additions and 740 deletions
|
|
@ -6,6 +6,8 @@
|
|||
* must never be returned by any endpoint on this channel.
|
||||
*/
|
||||
|
||||
import { normalizeAgentPresetCatalog, normalizeAgentPresetId } from "../../agent-preset.js";
|
||||
|
||||
export const FEISHU_RPC_CHANNEL = "/feishu";
|
||||
|
||||
export const FEISHU_ENDPOINTS = Object.freeze({
|
||||
|
|
@ -19,6 +21,7 @@ export const FEISHU_ENDPOINTS = Object.freeze({
|
|||
disconnectBot: "bot.disconnect",
|
||||
deleteBot: "bot.delete",
|
||||
setWorkspace: "bot.workspace.set",
|
||||
setAgentPreset: "bot.preset.set",
|
||||
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
|
||||
testConnection: "connection.test",
|
||||
disconnect: "connection.disconnect",
|
||||
|
|
@ -182,6 +185,7 @@ export function normalizeBotConnection(value, fallbackBotId) {
|
|||
connected,
|
||||
configured: value.configured !== false,
|
||||
workspace: optionalString(value.workspace)?.slice(0, 4_096) ?? "",
|
||||
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
||||
bot: normalizeBot(value.bot),
|
||||
health: normalizeHealth(value.health, connected),
|
||||
error: normalizeError(value.error),
|
||||
|
|
@ -236,6 +240,7 @@ export function normalizeBotsSnapshot(value) {
|
|||
? normalizeProvisioning(value.provisioning)
|
||||
: undefined,
|
||||
error: normalizeError(value.error),
|
||||
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ import {
|
|||
} from "./api.js";
|
||||
import { useAnimationFrameScheduler } from "../../lifecycle.js";
|
||||
import { WorkspaceEditor } from "../../workspace-editor.js";
|
||||
import {
|
||||
AgentPresetCatalogContext,
|
||||
AgentPresetEditor,
|
||||
EMPTY_AGENT_PRESET_CATALOG,
|
||||
} from "../../agent-preset.js";
|
||||
import { useWorkspaceSnapshotFence } from "../../workspace-snapshot-fence.js";
|
||||
import { installFeishuStyles } from "./styles.js";
|
||||
|
||||
|
|
@ -418,6 +423,7 @@ export function BotCard({
|
|||
onReconnect,
|
||||
onRepairCallback,
|
||||
onWorkspaceSave,
|
||||
onAgentPresetSave,
|
||||
onRequestRemove,
|
||||
onConfirmRemove,
|
||||
onCancelRemove,
|
||||
|
|
@ -468,6 +474,11 @@ export function BotCard({
|
|||
disabled: Boolean(busy),
|
||||
onSave: onWorkspaceSave,
|
||||
}),
|
||||
h(AgentPresetEditor, {
|
||||
agentPreset: connection.agentPreset,
|
||||
disabled: Boolean(busy),
|
||||
onSave: onAgentPresetSave,
|
||||
}),
|
||||
h("div", { className: "bxf-connectedFooter dim-cardFooter" },
|
||||
summary ? h("div", { className: "bxf-healthSummary dim-cardSummary", "data-error": actionError || connection.error ? "true" : undefined },
|
||||
summary) : null,
|
||||
|
|
@ -524,6 +535,7 @@ function BotList(props) {
|
|||
onReconnect: () => props.onReconnect(bot),
|
||||
onRepairCallback: () => props.onRepairCallback(bot),
|
||||
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
|
||||
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
|
||||
onRequestRemove: () => props.onRequestRemove(bot),
|
||||
onConfirmRemove: () => props.onConfirmRemove(bot),
|
||||
onCancelRemove: props.onCancelRemove,
|
||||
|
|
@ -575,6 +587,7 @@ export function mergeFeishuSnapshotState(
|
|||
provisioning,
|
||||
pageError: null,
|
||||
statusError: null,
|
||||
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -587,6 +600,7 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|||
provisioning: null,
|
||||
pageError: null,
|
||||
statusError: null,
|
||||
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
||||
});
|
||||
const [pageBusy, setPageBusy] = React.useState(false);
|
||||
const [provisionBusy, setProvisionBusy] = React.useState(false);
|
||||
|
|
@ -1067,6 +1081,26 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|||
}
|
||||
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
||||
|
||||
const saveAgentPreset = React.useCallback(async (connection, agentPreset) => {
|
||||
const { botId } = connection;
|
||||
const snapshotVersion = workspaceFence.beginMutation();
|
||||
setBotBusy(botId, "preset");
|
||||
setBotError(botId, null);
|
||||
try {
|
||||
const snapshot = normalizeBotsSnapshot(await invoke(
|
||||
FEISHU_ENDPOINTS.setAgentPreset,
|
||||
{ botId, agentPreset },
|
||||
));
|
||||
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
||||
mergeSnapshot(snapshot);
|
||||
}
|
||||
} finally {
|
||||
const shouldRefresh = workspaceFence.endMutation();
|
||||
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
||||
if (mountedRef.current) setBotBusy(botId, null);
|
||||
}
|
||||
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
||||
|
||||
const requestRemove = React.useCallback((connection) => {
|
||||
setRemoveTargetId(connection.botId);
|
||||
}, []);
|
||||
|
|
@ -1173,7 +1207,9 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|||
else removeButtonRefs.current.delete(botId);
|
||||
}, []);
|
||||
|
||||
return h("section", { className: "bxf-page dim-channelPage", "aria-label": "飞书机器人设置" },
|
||||
return h(AgentPresetCatalogContext.Provider, {
|
||||
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
||||
}, h("section", { className: "bxf-page dim-channelPage", "aria-label": "飞书机器人设置" },
|
||||
h(Heading, {
|
||||
totals: model.totals,
|
||||
onAdd: () => void startProvisioning(),
|
||||
|
|
@ -1217,6 +1253,7 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|||
onReconnect: (bot) => void reconnectOneBot(bot),
|
||||
onRepairCallback: repairCallback,
|
||||
onWorkspaceSave: saveWorkspace,
|
||||
onAgentPresetSave: saveAgentPreset,
|
||||
onRequestRemove: requestRemove,
|
||||
onConfirmRemove: (bot) => void confirmRemove(bot),
|
||||
onCancelRemove: cancelRemove,
|
||||
|
|
@ -1225,7 +1262,7 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|||
})
|
||||
: null,
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export function apply(ctx) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue