refactor(channels): share native command session targets
This commit is contained in:
parent
6016e22cc0
commit
e381ab630e
48
src/channels/native-command-session-targets.test.ts
Normal file
48
src/channels/native-command-session-targets.test.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveNativeCommandSessionTargets } from "./native-command-session-targets.js";
|
||||
|
||||
describe("resolveNativeCommandSessionTargets", () => {
|
||||
it("uses the bound session for both targets when present", () => {
|
||||
expect(
|
||||
resolveNativeCommandSessionTargets({
|
||||
agentId: "codex",
|
||||
sessionPrefix: "discord:slash",
|
||||
userId: "user-1",
|
||||
targetSessionKey: "agent:codex:discord:channel:chan-1",
|
||||
boundSessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
}),
|
||||
).toEqual({
|
||||
sessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
commandTargetSessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to the routed session target when unbound", () => {
|
||||
expect(
|
||||
resolveNativeCommandSessionTargets({
|
||||
agentId: "qwen",
|
||||
sessionPrefix: "telegram:slash",
|
||||
userId: "user-1",
|
||||
targetSessionKey: "agent:qwen:telegram:direct:user-1",
|
||||
}),
|
||||
).toEqual({
|
||||
sessionKey: "agent:qwen:telegram:slash:user-1",
|
||||
commandTargetSessionKey: "agent:qwen:telegram:direct:user-1",
|
||||
});
|
||||
});
|
||||
|
||||
it("supports lowercase session keys for providers that already normalize", () => {
|
||||
expect(
|
||||
resolveNativeCommandSessionTargets({
|
||||
agentId: "Qwen",
|
||||
sessionPrefix: "Slack:Slash",
|
||||
userId: "U123",
|
||||
targetSessionKey: "agent:qwen:slack:channel:c1",
|
||||
lowercaseSessionKey: true,
|
||||
}),
|
||||
).toEqual({
|
||||
sessionKey: "agent:qwen:slack:slash:u123",
|
||||
commandTargetSessionKey: "agent:qwen:slack:channel:c1",
|
||||
});
|
||||
});
|
||||
});
|
||||
19
src/channels/native-command-session-targets.ts
Normal file
19
src/channels/native-command-session-targets.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export type ResolveNativeCommandSessionTargetsParams = {
|
||||
agentId: string;
|
||||
sessionPrefix: string;
|
||||
userId: string;
|
||||
targetSessionKey: string;
|
||||
boundSessionKey?: string;
|
||||
lowercaseSessionKey?: boolean;
|
||||
};
|
||||
|
||||
export function resolveNativeCommandSessionTargets(
|
||||
params: ResolveNativeCommandSessionTargetsParams,
|
||||
) {
|
||||
const rawSessionKey =
|
||||
params.boundSessionKey ?? `agent:${params.agentId}:${params.sessionPrefix}:${params.userId}`;
|
||||
return {
|
||||
sessionKey: params.lowercaseSessionKey ? rawSessionKey.toLowerCase() : rawSessionKey,
|
||||
commandTargetSessionKey: params.boundSessionKey ?? params.targetSessionKey,
|
||||
};
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveDiscordNativeCommandSessionTargets } from "./native-command-session-targets.js";
|
||||
|
||||
describe("resolveDiscordNativeCommandSessionTargets", () => {
|
||||
it("uses the bound session for both targets when present", () => {
|
||||
expect(
|
||||
resolveDiscordNativeCommandSessionTargets({
|
||||
boundSessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
effectiveRoute: {
|
||||
agentId: "codex",
|
||||
sessionKey: "agent:codex:discord:channel:chan-1",
|
||||
},
|
||||
sessionPrefix: "discord:slash",
|
||||
userId: "user-1",
|
||||
}),
|
||||
).toEqual({
|
||||
sessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
commandTargetSessionKey: "agent:codex:acp:binding:discord:default:seed",
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to the routed slash and command target session keys", () => {
|
||||
expect(
|
||||
resolveDiscordNativeCommandSessionTargets({
|
||||
effectiveRoute: {
|
||||
agentId: "qwen",
|
||||
sessionKey: "agent:qwen:discord:channel:chan-1",
|
||||
},
|
||||
sessionPrefix: "discord:slash",
|
||||
userId: "user-1",
|
||||
}),
|
||||
).toEqual({
|
||||
sessionKey: "agent:qwen:discord:slash:user-1",
|
||||
commandTargetSessionKey: "agent:qwen:discord:channel:chan-1",
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,22 +0,0 @@
|
||||
export type ResolveDiscordNativeCommandSessionTargetsParams = {
|
||||
boundSessionKey?: string;
|
||||
effectiveRoute: {
|
||||
agentId: string;
|
||||
sessionKey: string;
|
||||
};
|
||||
sessionPrefix: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export function resolveDiscordNativeCommandSessionTargets(
|
||||
params: ResolveDiscordNativeCommandSessionTargetsParams,
|
||||
) {
|
||||
const sessionKey =
|
||||
params.boundSessionKey ??
|
||||
`agent:${params.effectiveRoute.agentId}:${params.sessionPrefix}:${params.userId}`;
|
||||
const commandTargetSessionKey = params.boundSessionKey ?? params.effectiveRoute.sessionKey;
|
||||
return {
|
||||
sessionKey,
|
||||
commandTargetSessionKey,
|
||||
};
|
||||
}
|
||||
@ -41,6 +41,7 @@ import { resolveStoredModelOverride } from "../../auto-reply/reply/model-selecti
|
||||
import { dispatchReplyWithDispatcher } from "../../auto-reply/reply/provider-dispatcher.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
|
||||
import { resolveNativeCommandSessionTargets } from "../../channels/native-command-session-targets.js";
|
||||
import { createReplyPrefixOptions } from "../../channels/reply-prefix.js";
|
||||
import type { OpenClawConfig, loadConfig } from "../../config/config.js";
|
||||
import { isDangerousNameMatchingEnabled } from "../../config/dangerous-name-matching.js";
|
||||
@ -83,7 +84,6 @@ import {
|
||||
type DiscordModelPickerCommandContext,
|
||||
} from "./model-picker.js";
|
||||
import { buildDiscordNativeCommandContext } from "./native-command-context.js";
|
||||
import { resolveDiscordNativeCommandSessionTargets } from "./native-command-session-targets.js";
|
||||
import {
|
||||
resolveDiscordBoundConversationRoute,
|
||||
resolveDiscordEffectiveRoute,
|
||||
@ -1645,11 +1645,12 @@ async function dispatchDiscordCommandInteraction(params: {
|
||||
configuredRoute,
|
||||
matchedBy: configuredBinding ? "binding.channel" : undefined,
|
||||
});
|
||||
const { sessionKey, commandTargetSessionKey } = resolveDiscordNativeCommandSessionTargets({
|
||||
boundSessionKey,
|
||||
effectiveRoute,
|
||||
const { sessionKey, commandTargetSessionKey } = resolveNativeCommandSessionTargets({
|
||||
agentId: effectiveRoute.agentId,
|
||||
sessionPrefix,
|
||||
userId: user.id,
|
||||
targetSessionKey: effectiveRoute.sessionKey,
|
||||
boundSessionKey,
|
||||
});
|
||||
const ctxPayload = buildDiscordNativeCommandContext({
|
||||
prompt,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
} from "../../auto-reply/commands-registry.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
|
||||
import { resolveNativeCommandSessionTargets } from "../../channels/native-command-session-targets.js";
|
||||
import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "../../config/commands.js";
|
||||
import { danger, logVerbose } from "../../globals.js";
|
||||
import { chunkItems } from "../../utils/chunk-items.js";
|
||||
@ -546,6 +547,13 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
channelConfig,
|
||||
});
|
||||
|
||||
const { sessionKey, commandTargetSessionKey } = resolveNativeCommandSessionTargets({
|
||||
agentId: route.agentId,
|
||||
sessionPrefix: slashCommand.sessionPrefix,
|
||||
userId: command.user_id,
|
||||
targetSessionKey: route.sessionKey,
|
||||
lowercaseSessionKey: true,
|
||||
});
|
||||
const ctxPayload = finalizeInboundContext({
|
||||
Body: prompt,
|
||||
BodyForAgent: prompt,
|
||||
@ -580,9 +588,8 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
WasMentioned: true,
|
||||
MessageSid: command.trigger_id,
|
||||
Timestamp: Date.now(),
|
||||
SessionKey:
|
||||
`agent:${route.agentId}:${slashCommand.sessionPrefix}:${command.user_id}`.toLowerCase(),
|
||||
CommandTargetSessionKey: route.sessionKey,
|
||||
SessionKey: sessionKey,
|
||||
CommandTargetSessionKey: commandTargetSessionKey,
|
||||
AccountId: route.accountId,
|
||||
CommandSource: "native" as const,
|
||||
CommandAuthorized: commandAuthorized,
|
||||
|
||||
@ -14,6 +14,7 @@ import { finalizeInboundContext } from "../auto-reply/reply/inbound-context.js";
|
||||
import { dispatchReplyWithBufferedBlockDispatcher } from "../auto-reply/reply/provider-dispatcher.js";
|
||||
import { listSkillCommandsForAgents } from "../auto-reply/skill-commands.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "../channels/command-gating.js";
|
||||
import { resolveNativeCommandSessionTargets } from "../channels/native-command-session-targets.js";
|
||||
import { createReplyPrefixOptions } from "../channels/reply-prefix.js";
|
||||
import { recordInboundSessionMetaSafe } from "../channels/session-meta.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
@ -638,6 +639,13 @@ export const registerTelegramNativeCommands = ({
|
||||
groupConfig,
|
||||
topicConfig,
|
||||
});
|
||||
const { sessionKey: commandSessionKey, commandTargetSessionKey } =
|
||||
resolveNativeCommandSessionTargets({
|
||||
agentId: route.agentId,
|
||||
sessionPrefix: "telegram:slash",
|
||||
userId: String(senderId || chatId),
|
||||
targetSessionKey: sessionKey,
|
||||
});
|
||||
const conversationLabel = isGroup
|
||||
? msg.chat.title
|
||||
? `${msg.chat.title} id:${chatId}`
|
||||
@ -665,9 +673,9 @@ export const registerTelegramNativeCommands = ({
|
||||
WasMentioned: true,
|
||||
CommandAuthorized: commandAuthorized,
|
||||
CommandSource: "native" as const,
|
||||
SessionKey: `agent:${route.agentId}:telegram:slash:${senderId || chatId}`,
|
||||
SessionKey: commandSessionKey,
|
||||
AccountId: route.accountId,
|
||||
CommandTargetSessionKey: sessionKey,
|
||||
CommandTargetSessionKey: commandTargetSessionKey,
|
||||
MessageThreadId: threadSpec.id,
|
||||
IsForum: isForum,
|
||||
// Originating context for sub-agent announce routing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user