fix: gate tool summaries to direct chats (#2673) (thanks @Lukavyi)
This commit is contained in:
parent
8179e9b499
commit
e0e37af470
@ -73,6 +73,7 @@ Status: beta.
|
|||||||
- **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed).
|
- **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed).
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
- Telegram: restore verbose tool summaries for direct messages only. (#2673) Thanks @Lukavyi.
|
||||||
- Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald.
|
- Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald.
|
||||||
- Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald.
|
- Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald.
|
||||||
- Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma.
|
- Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma.
|
||||||
|
|||||||
@ -154,7 +154,7 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
const replyResolver = async (
|
const replyResolver = async (
|
||||||
_ctx: MsgContext,
|
_ctx: MsgContext,
|
||||||
opts: GetReplyOptions | undefined,
|
opts: GetReplyOptions | undefined,
|
||||||
_cfg: ClawdbotConfig,
|
_cfg: MoltbotConfig,
|
||||||
) => {
|
) => {
|
||||||
expect(opts?.onToolResult).toBeDefined();
|
expect(opts?.onToolResult).toBeDefined();
|
||||||
expect(typeof opts?.onToolResult).toBe("function");
|
expect(typeof opts?.onToolResult).toBe("function");
|
||||||
@ -170,7 +170,7 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
handled: false,
|
handled: false,
|
||||||
aborted: false,
|
aborted: false,
|
||||||
});
|
});
|
||||||
const cfg = {} as ClawdbotConfig;
|
const cfg = {} as MoltbotConfig;
|
||||||
const dispatcher = createDispatcher();
|
const dispatcher = createDispatcher();
|
||||||
const ctx = buildTestCtx({
|
const ctx = buildTestCtx({
|
||||||
Provider: "telegram",
|
Provider: "telegram",
|
||||||
@ -190,12 +190,37 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
expect(dispatcher.sendFinalReply).toHaveBeenCalledTimes(1);
|
expect(dispatcher.sendFinalReply).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not provide onToolResult in channel sessions", async () => {
|
||||||
|
mocks.tryFastAbortFromMessage.mockResolvedValue({
|
||||||
|
handled: false,
|
||||||
|
aborted: false,
|
||||||
|
});
|
||||||
|
const cfg = {} as MoltbotConfig;
|
||||||
|
const dispatcher = createDispatcher();
|
||||||
|
const ctx = buildTestCtx({
|
||||||
|
Provider: "slack",
|
||||||
|
ChatType: "channel",
|
||||||
|
});
|
||||||
|
|
||||||
|
const replyResolver = async (
|
||||||
|
_ctx: MsgContext,
|
||||||
|
opts: GetReplyOptions | undefined,
|
||||||
|
_cfg: MoltbotConfig,
|
||||||
|
) => {
|
||||||
|
expect(opts?.onToolResult).toBeUndefined();
|
||||||
|
return { text: "hi" } satisfies ReplyPayload;
|
||||||
|
};
|
||||||
|
|
||||||
|
await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver });
|
||||||
|
expect(dispatcher.sendFinalReply).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("sends tool results via dispatcher in DM sessions", async () => {
|
it("sends tool results via dispatcher in DM sessions", async () => {
|
||||||
mocks.tryFastAbortFromMessage.mockResolvedValue({
|
mocks.tryFastAbortFromMessage.mockResolvedValue({
|
||||||
handled: false,
|
handled: false,
|
||||||
aborted: false,
|
aborted: false,
|
||||||
});
|
});
|
||||||
const cfg = {} as ClawdbotConfig;
|
const cfg = {} as MoltbotConfig;
|
||||||
const dispatcher = createDispatcher();
|
const dispatcher = createDispatcher();
|
||||||
const ctx = buildTestCtx({
|
const ctx = buildTestCtx({
|
||||||
Provider: "telegram",
|
Provider: "telegram",
|
||||||
@ -205,7 +230,7 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
const replyResolver = async (
|
const replyResolver = async (
|
||||||
_ctx: MsgContext,
|
_ctx: MsgContext,
|
||||||
opts: GetReplyOptions | undefined,
|
opts: GetReplyOptions | undefined,
|
||||||
_cfg: ClawdbotConfig,
|
_cfg: MoltbotConfig,
|
||||||
) => {
|
) => {
|
||||||
// Simulate tool result emission
|
// Simulate tool result emission
|
||||||
await opts?.onToolResult?.({ text: "🔧 exec: ls" });
|
await opts?.onToolResult?.({ text: "🔧 exec: ls" });
|
||||||
@ -224,7 +249,7 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
handled: false,
|
handled: false,
|
||||||
aborted: false,
|
aborted: false,
|
||||||
});
|
});
|
||||||
const cfg = {} as ClawdbotConfig;
|
const cfg = {} as MoltbotConfig;
|
||||||
const dispatcher = createDispatcher();
|
const dispatcher = createDispatcher();
|
||||||
const ctx = buildTestCtx({
|
const ctx = buildTestCtx({
|
||||||
Provider: "telegram",
|
Provider: "telegram",
|
||||||
@ -235,7 +260,7 @@ describe("dispatchReplyFromConfig", () => {
|
|||||||
const replyResolver = async (
|
const replyResolver = async (
|
||||||
_ctx: MsgContext,
|
_ctx: MsgContext,
|
||||||
opts: GetReplyOptions | undefined,
|
opts: GetReplyOptions | undefined,
|
||||||
_cfg: ClawdbotConfig,
|
_cfg: MoltbotConfig,
|
||||||
) => {
|
) => {
|
||||||
expect(opts?.onToolResult).toBeUndefined();
|
expect(opts?.onToolResult).toBeUndefined();
|
||||||
return { text: "hi" } satisfies ReplyPayload;
|
return { text: "hi" } satisfies ReplyPayload;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { MoltbotConfig } from "../../config/config.js";
|
import type { MoltbotConfig } from "../../config/config.js";
|
||||||
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
||||||
|
import { normalizeChatType } from "../../channels/chat-type.js";
|
||||||
import { loadSessionStore, resolveStorePath } from "../../config/sessions.js";
|
import { loadSessionStore, resolveStorePath } from "../../config/sessions.js";
|
||||||
import { logVerbose } from "../../globals.js";
|
import { logVerbose } from "../../globals.js";
|
||||||
import { isDiagnosticsEnabled } from "../../infra/diagnostic-events.js";
|
import { isDiagnosticsEnabled } from "../../infra/diagnostic-events.js";
|
||||||
@ -196,6 +197,8 @@ export async function dispatchReplyFromConfig(params: {
|
|||||||
const shouldRouteToOriginating =
|
const shouldRouteToOriginating =
|
||||||
isRoutableChannel(originatingChannel) && originatingTo && originatingChannel !== currentSurface;
|
isRoutableChannel(originatingChannel) && originatingTo && originatingChannel !== currentSurface;
|
||||||
const ttsChannel = shouldRouteToOriginating ? originatingChannel : currentSurface;
|
const ttsChannel = shouldRouteToOriginating ? originatingChannel : currentSurface;
|
||||||
|
const normalizedChatType = normalizeChatType(ctx.ChatType);
|
||||||
|
const shouldEmitToolSummaries = normalizedChatType === "direct" && ctx.CommandSource !== "native";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to send a payload via route-reply (async).
|
* Helper to send a payload via route-reply (async).
|
||||||
@ -276,27 +279,26 @@ export async function dispatchReplyFromConfig(params: {
|
|||||||
ctx,
|
ctx,
|
||||||
{
|
{
|
||||||
...params.replyOptions,
|
...params.replyOptions,
|
||||||
onToolResult:
|
onToolResult: shouldEmitToolSummaries
|
||||||
ctx.ChatType !== "group" && ctx.CommandSource !== "native"
|
? (payload: ReplyPayload) => {
|
||||||
? (payload: ReplyPayload) => {
|
const run = async () => {
|
||||||
const run = async () => {
|
const ttsPayload = await maybeApplyTtsToPayload({
|
||||||
const ttsPayload = await maybeApplyTtsToPayload({
|
payload,
|
||||||
payload,
|
cfg,
|
||||||
cfg,
|
channel: ttsChannel,
|
||||||
channel: ttsChannel,
|
kind: "tool",
|
||||||
kind: "tool",
|
inboundAudio,
|
||||||
inboundAudio,
|
ttsAuto: sessionTtsAuto,
|
||||||
ttsAuto: sessionTtsAuto,
|
});
|
||||||
});
|
if (shouldRouteToOriginating) {
|
||||||
if (shouldRouteToOriginating) {
|
await sendPayloadAsync(ttsPayload, undefined, false);
|
||||||
await sendPayloadAsync(ttsPayload, undefined, false);
|
} else {
|
||||||
} else {
|
dispatcher.sendToolResult(ttsPayload);
|
||||||
dispatcher.sendToolResult(ttsPayload);
|
}
|
||||||
}
|
};
|
||||||
};
|
return run();
|
||||||
return run();
|
}
|
||||||
}
|
: undefined,
|
||||||
: undefined,
|
|
||||||
onBlockReply: (payload: ReplyPayload, context) => {
|
onBlockReply: (payload: ReplyPayload, context) => {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
// Accumulate block text for TTS generation after streaming
|
// Accumulate block text for TTS generation after streaming
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user