




















@@ -1,6 +1,11 @@
11import type { SlackActionMiddlewareArgs, SlackCommandMiddlewareArgs } from "@slack/bolt";
2+import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
23import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
3-import type { ChatCommandDefinition } from "openclaw/plugin-sdk/command-auth";
4+import {
5+formatCommandArgMenuTitle,
6+resolveStoredModelOverride,
7+type ChatCommandDefinition,
8+} from "openclaw/plugin-sdk/command-auth";
49import {
510type CommandArgs,
611resolveCommandAuthorizedFromAuthorizers,
@@ -9,11 +14,18 @@ import {
914import {
1015resolveNativeCommandsEnabled,
1116resolveNativeSkillsEnabled,
17+loadSessionStore,
18+resolveStorePath,
1219} from "openclaw/plugin-sdk/config-runtime";
1320import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
1421import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
22+import type { ResolvedAgentRoute } from "openclaw/plugin-sdk/routing";
1523import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
16-import { chunkItems, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
24+import {
25+chunkItems,
26+normalizeLowercaseStringOrEmpty,
27+normalizeOptionalString,
28+} from "openclaw/plugin-sdk/text-runtime";
1729import type { ResolvedSlackAccount } from "../accounts.js";
1830import { truncateSlackText } from "../truncate.js";
1931import { resolveSlackAllowListMatch, resolveSlackUserAllowed } from "./allow-list.js";
@@ -74,6 +86,51 @@ function loadSlashSkillCommandsRuntime() {
7486return slashSkillCommandsRuntimePromise;
7587}
768889+function resolveSlackCommandMenuModelContext(params: {
90+cfg: SlackMonitorContext["cfg"];
91+agentId: string;
92+sessionKey: string;
93+}): { provider?: string; model?: string } {
94+if (!params.sessionKey.trim()) {
95+return {};
96+}
97+try {
98+const defaultModel = resolveDefaultModelForAgent({
99+cfg: params.cfg,
100+agentId: params.agentId,
101+});
102+const storePath = resolveStorePath(params.cfg.session?.store, { agentId: params.agentId });
103+const store = loadSessionStore(storePath);
104+const entry = store[params.sessionKey];
105+if (entry?.modelOverrideSource === "auto" && normalizeOptionalString(entry.modelOverride)) {
106+return { provider: defaultModel.provider, model: defaultModel.model };
107+}
108+const override = resolveStoredModelOverride({
109+sessionEntry: entry,
110+sessionStore: store,
111+sessionKey: params.sessionKey,
112+defaultProvider: defaultModel.provider,
113+});
114+if (override?.model) {
115+return {
116+provider: override.provider || defaultModel.provider,
117+model: override.model,
118+};
119+}
120+const provider =
121+normalizeOptionalString(entry?.providerOverride) ??
122+normalizeOptionalString(entry?.modelProvider);
123+const model =
124+normalizeOptionalString(entry?.modelOverride) ?? normalizeOptionalString(entry?.model);
125+return {
126+ ...(provider ? { provider } : {}),
127+ ...(model ? { model } : {}),
128+};
129+} catch {
130+return {};
131+}
132+}
133+77134type EncodedMenuChoice = SlackExternalArgMenuChoice;
78135const slackExternalArgMenuStore = createSlackExternalArgMenuStore();
79136@@ -496,17 +553,49 @@ export async function registerSlackMonitorSlashCommands(params: {
496553}
497554}
498555556+let resolvedSlashRoute: ResolvedAgentRoute | undefined;
557+const resolveSlashRoute = async () => {
558+if (resolvedSlashRoute) {
559+return resolvedSlashRoute;
560+}
561+const { resolveAgentRoute } = await loadSlashDispatchRuntime();
562+resolvedSlashRoute = resolveAgentRoute({
563+ cfg,
564+channel: "slack",
565+accountId: account.accountId,
566+teamId: ctx.teamId || undefined,
567+peer: {
568+kind: isDirectMessage ? "direct" : isRoom ? "channel" : "group",
569+id: isDirectMessage ? command.user_id : command.channel_id,
570+},
571+});
572+return resolvedSlashRoute;
573+};
574+499575if (commandDefinition && supportsInteractiveArgMenus) {
500576const { resolveCommandArgMenu } = await loadSlashCommandsRuntime();
577+const menuNeedsModelContext =
578+!(commandArgs?.raw && !commandArgs.values) &&
579+commandDefinition.args?.some(
580+(arg) => typeof arg.choices === "function" && commandArgs?.values?.[arg.name] == null,
581+);
582+const menuRoute = menuNeedsModelContext ? await resolveSlashRoute() : undefined;
583+const menuModelContext = menuRoute
584+ ? resolveSlackCommandMenuModelContext({
585+ cfg,
586+agentId: menuRoute.agentId,
587+sessionKey: menuRoute.sessionKey,
588+})
589+ : {};
501590const menu = resolveCommandArgMenu({
502591command: commandDefinition,
503592args: commandArgs,
504593 cfg,
594+ ...menuModelContext,
505595});
506596if (menu) {
507597const commandLabel = commandDefinition.nativeName ?? commandDefinition.key;
508-const title =
509-menu.title ?? `Choose ${menu.arg.description || menu.arg.name} for /${commandLabel}.`;
598+const title = formatCommandArgMenuTitle({ command: commandDefinition, menu });
510599const blocks = buildSlackCommandArgMenuBlocks({
511600 title,
512601command: commandLabel,
@@ -539,16 +628,18 @@ export async function registerSlackMonitorSlashCommands(params: {
539628 resolveMarkdownTableMode,
540629} = await loadSlashDispatchRuntime();
541630542-const route = resolveAgentRoute({
543- cfg,
544-channel: "slack",
545-accountId: account.accountId,
546-teamId: ctx.teamId || undefined,
547-peer: {
548-kind: isDirectMessage ? "direct" : isRoom ? "channel" : "group",
549-id: isDirectMessage ? command.user_id : command.channel_id,
550-},
551-});
631+const route =
632+resolvedSlashRoute ??
633+resolveAgentRoute({
634+ cfg,
635+channel: "slack",
636+accountId: account.accountId,
637+teamId: ctx.teamId || undefined,
638+peer: {
639+kind: isDirectMessage ? "direct" : isRoom ? "channel" : "group",
640+id: isDirectMessage ? command.user_id : command.channel_id,
641+},
642+});
552643553644const { untrustedChannelMetadata, groupSystemPrompt } = resolveSlackRoomContextHints({
554645 isRoomish,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。