import { afterEach, describe, expect, it } from "vitest"; import type { SubagentRunRecord } from "../../agents/subagent-registry.js"; import type { ChannelPlugin } from "../../channels/plugins/types.js"; import type { OpenClawConfig } from "../../config/config.js"; import { formatDurationCompact } from "../../infra/format-time/format-duration.js"; import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js"; import {
createChannelTestPluginBase,
createTestRegistry,
} from "../../test-utils/channel-plugins.js"; import type { TemplateContext } from "../templating.js"; import { buildThreadingToolContext } from "./agent-runner-utils.js"; import { applyReplyThreading } from "./reply-payloads.js"; import {
formatRunLabel,
formatRunStatus,
resolveSubagentLabel,
sortSubagentRuns,
} from "./subagents-utils.js";
it("uses the recipient id for WhatsApp without origin routing metadata", () => { const sessionCtx = {
Provider: "whatsapp",
From: "123@g.us",
To: "+15550001",
} as TemplateContext;
const result = buildThreadingToolContext({
sessionCtx,
config: cfg,
hasRepliedRef: undefined,
});
it("uses the recipient id for other channels", () => { const sessionCtx = {
Provider: "telegram",
From: "user:42",
To: "chat:99",
} as TemplateContext;
const result = buildThreadingToolContext({
sessionCtx,
config: cfg,
hasRepliedRef: undefined,
});
it("uses raw signal direct targets for tool context without provider-specific normalization", () => { const sessionCtx = {
Provider: "signal",
ChatType: "direct",
From: "signal:+15550001",
To: "signal:+15550002",
} as TemplateContext;
const result = buildThreadingToolContext({
sessionCtx,
config: cfg,
hasRepliedRef: undefined,
});
it("keeps raw signal group ids for tool context", () => { const sessionCtx = {
Provider: "signal",
ChatType: "group",
To: "signal:group:VWATOdKF2hc8zdOS76q9tb0+5BI522e03QLDAq/9yPg=",
} as TemplateContext;
const result = buildThreadingToolContext({
sessionCtx,
config: cfg,
hasRepliedRef: undefined,
});
it("threads only first payload when mode is 'first'", () => { const result = applyReplyThreading({
payloads: [{ text: "A" }, { text: "B" }],
replyToMode: "first",
currentMessageId: "42",
});
it("threads only first payload when mode is 'batched' and the turn is batched", () => { const result = applyReplyThreading({
payloads: [{ text: "A" }, { text: "B" }],
replyToMode: "batched",
currentMessageId: "42",
replyThreading: { implicitCurrentMessage: "allow" },
});
it("does not bypass off mode for Slack when reply is implicit", () => { const result = applyReplyThreading({
payloads: [{ text: "A" }],
replyToMode: "off",
replyToChannel: "slack",
currentMessageId: "42",
});
it("resolves [[reply_to_current]] to currentMessageId when replyToMode is 'all'", () => { // Mattermost-style scenario: agent responds with [[reply_to_current]] and replyToMode // is "all". The tag should resolve to the inbound message id. const result = applyReplyThreading({
payloads: [{ text: "[[reply_to_current]] some reply text" }],
replyToMode: "all",
currentMessageId: "mm-post-abc123",
});
it("sets replyToId via implicit threading when replyToMode is 'all'", () => { // Even without explicit tags, replyToMode "all" should set replyToId // to currentMessageId for threading. const result = applyReplyThreading({
payloads: [{ text: "hello" }],
replyToMode: "all",
currentMessageId: "mm-post-abc123",
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.