mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-15 19:21:08 +00:00
fix(cycles): split reply payload and option contracts
This commit is contained in:
@@ -8,8 +8,9 @@ import {
|
||||
type TextContent,
|
||||
} from "@mariozechner/pi-ai";
|
||||
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
||||
import type { GetReplyOptions } from "../auto-reply/get-reply-options.types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type { ReasoningLevel, ThinkLevel } from "../auto-reply/thinking.js";
|
||||
import type { GetReplyOptions, ReplyPayload } from "../auto-reply/types.js";
|
||||
import {
|
||||
resolveSessionFilePath,
|
||||
resolveSessionFilePathOptions,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import { normalizeReplyPayload } from "../../auto-reply/reply/normalize-reply.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import { getChannelPlugin, normalizeChannelId } from "../../channels/plugins/index.js";
|
||||
import { createReplyPrefixContext } from "../../channels/reply-prefix.js";
|
||||
import { createOutboundSendDeps, type CliDeps } from "../../cli/outbound-send-deps.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
||||
import type { ReplyPayload } from "../../../auto-reply/reply-payload.js";
|
||||
import type { ReplyOperation } from "../../../auto-reply/reply/reply-run-registry.js";
|
||||
import type { ReasoningLevel, ThinkLevel, VerboseLevel } from "../../../auto-reply/thinking.js";
|
||||
import type { ReplyPayload } from "../../../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import type { PromptImageOrderEntry } from "../../../media/prompt-image-order.js";
|
||||
import type { CommandQueueEnqueueFn } from "../../../process/command-queue.types.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { setReplyPayloadMetadata } from "../auto-reply/reply-payload.js";
|
||||
import { parseReplyDirectives } from "../auto-reply/reply/reply-directives.js";
|
||||
import { createStreamingDirectiveAccumulator } from "../auto-reply/reply/streaming-directives.js";
|
||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
import { formatToolAggregate } from "../auto-reply/tool-meta.js";
|
||||
import { setReplyPayloadMetadata } from "../auto-reply/types.js";
|
||||
import { emitAgentEvent } from "../infra/agent-events.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import type { InlineCodeState } from "../markdown/code-spans.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AgentSession } from "@mariozechner/pi-coding-agent";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type { ReasoningLevel, VerboseLevel } from "../auto-reply/thinking.js";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { HookRunner } from "../plugins/hooks.js";
|
||||
import type { AgentInternalEvent } from "./internal-events.js";
|
||||
|
||||
149
src/auto-reply/get-reply-options.types.ts
Normal file
149
src/auto-reply/get-reply-options.types.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
||||
import type { PromptImageOrderEntry } from "../media/prompt-image-order.js";
|
||||
import type { ReplyPayload } from "./reply-payload.js";
|
||||
import type { TypingController } from "./reply/typing.js";
|
||||
|
||||
export type BlockReplyContext = {
|
||||
abortSignal?: AbortSignal;
|
||||
timeoutMs?: number;
|
||||
/** Source assistant message index from the upstream stream, when available. */
|
||||
assistantMessageIndex?: number;
|
||||
};
|
||||
|
||||
/** Context passed to onModelSelected callback with actual model used. */
|
||||
export type ModelSelectedContext = {
|
||||
provider: string;
|
||||
model: string;
|
||||
thinkLevel: string | undefined;
|
||||
};
|
||||
|
||||
export type TypingPolicy =
|
||||
| "auto"
|
||||
| "user_message"
|
||||
| "system_event"
|
||||
| "internal_webchat"
|
||||
| "heartbeat";
|
||||
|
||||
export type ReplyThreadingPolicy = {
|
||||
/** Override implicit reply-to-current behavior for the current turn. */
|
||||
implicitCurrentMessage?: "default" | "allow" | "deny";
|
||||
};
|
||||
|
||||
export type GetReplyOptions = {
|
||||
/** Override run id for agent events (defaults to random UUID). */
|
||||
runId?: string;
|
||||
/** Abort signal for the underlying agent run. */
|
||||
abortSignal?: AbortSignal;
|
||||
/** Optional inbound images (used for webchat attachments). */
|
||||
images?: ImageContent[];
|
||||
/** Original inline/offloaded attachment order for inbound images. */
|
||||
imageOrder?: PromptImageOrderEntry[];
|
||||
/** Notifies when an agent run actually starts (useful for webchat command handling). */
|
||||
onAgentRunStart?: (runId: string) => void;
|
||||
onReplyStart?: () => Promise<void> | void;
|
||||
/** Called when the typing controller cleans up (e.g., run ended with NO_REPLY). */
|
||||
onTypingCleanup?: () => void;
|
||||
onTypingController?: (typing: TypingController) => void;
|
||||
isHeartbeat?: boolean;
|
||||
/** Policy-level typing control for run classes (user/system/internal/heartbeat). */
|
||||
typingPolicy?: TypingPolicy;
|
||||
/** Force-disable typing indicators for this run (system/internal/cross-channel routes). */
|
||||
suppressTyping?: boolean;
|
||||
/** Resolved heartbeat model override (provider/model string from merged per-agent config). */
|
||||
heartbeatModelOverride?: string;
|
||||
/** Controls bootstrap workspace context injection (default: full). */
|
||||
bootstrapContextMode?: "full" | "lightweight";
|
||||
/** If true, suppress tool error warning payloads for this run. */
|
||||
suppressToolErrorWarnings?: boolean;
|
||||
onPartialReply?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
onReasoningStream?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
/** Called when a thinking/reasoning block ends. */
|
||||
onReasoningEnd?: () => Promise<void> | void;
|
||||
/** Called when a new assistant message starts (e.g., after tool call or thinking block). */
|
||||
onAssistantMessageStart?: () => Promise<void> | void;
|
||||
/** Called synchronously when a block reply is logically emitted, before async
|
||||
* delivery drains. Useful for channels that need to rotate preview state at
|
||||
* block boundaries without waiting for transport acks. */
|
||||
onBlockReplyQueued?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<void> | void;
|
||||
onBlockReply?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<void> | void;
|
||||
onToolResult?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
/** Called when a tool phase starts/updates, before summary payloads are emitted. */
|
||||
onToolStart?: (payload: { name?: string; phase?: string }) => Promise<void> | void;
|
||||
/** Called when a concrete work item starts, updates, or completes. */
|
||||
onItemEvent?: (payload: {
|
||||
itemId?: string;
|
||||
kind?: string;
|
||||
title?: string;
|
||||
name?: string;
|
||||
phase?: string;
|
||||
status?: string;
|
||||
summary?: string;
|
||||
progressText?: string;
|
||||
approvalId?: string;
|
||||
approvalSlug?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when the agent emits a structured plan update. */
|
||||
onPlanUpdate?: (payload: {
|
||||
phase?: string;
|
||||
title?: string;
|
||||
explanation?: string;
|
||||
steps?: string[];
|
||||
source?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when an approval becomes pending or resolves. */
|
||||
onApprovalEvent?: (payload: {
|
||||
phase?: string;
|
||||
kind?: string;
|
||||
status?: string;
|
||||
title?: string;
|
||||
itemId?: string;
|
||||
toolCallId?: string;
|
||||
approvalId?: string;
|
||||
approvalSlug?: string;
|
||||
command?: string;
|
||||
host?: string;
|
||||
reason?: string;
|
||||
message?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when command output streams or completes. */
|
||||
onCommandOutput?: (payload: {
|
||||
itemId?: string;
|
||||
phase?: string;
|
||||
title?: string;
|
||||
toolCallId?: string;
|
||||
name?: string;
|
||||
output?: string;
|
||||
status?: string;
|
||||
exitCode?: number | null;
|
||||
durationMs?: number;
|
||||
cwd?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when a patch completes with a file summary. */
|
||||
onPatchSummary?: (payload: {
|
||||
itemId?: string;
|
||||
phase?: string;
|
||||
title?: string;
|
||||
toolCallId?: string;
|
||||
name?: string;
|
||||
added?: string[];
|
||||
modified?: string[];
|
||||
deleted?: string[];
|
||||
summary?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when context auto-compaction starts (allows UX feedback during the pause). */
|
||||
onCompactionStart?: () => Promise<void> | void;
|
||||
/** Called when context auto-compaction completes. */
|
||||
onCompactionEnd?: () => Promise<void> | void;
|
||||
/** Called when the actual model is selected (including after fallback).
|
||||
* Use this to get model/provider/thinkLevel for responsePrefix template interpolation. */
|
||||
onModelSelected?: (ctx: ModelSelectedContext) => void;
|
||||
disableBlockStreaming?: boolean;
|
||||
/** Timeout for block reply delivery (ms). */
|
||||
blockReplyTimeoutMs?: number;
|
||||
/** If provided, only load these skills for this session (empty = no skills). */
|
||||
skillFilter?: string[];
|
||||
/** Mutable ref to track if a reply was sent (for Slack "first" threading mode). */
|
||||
hasRepliedRef?: { value: boolean };
|
||||
/** Override agent timeout in seconds (0 = no timeout). Threads through to resolveAgentTimeoutMs. */
|
||||
timeoutOverrideSeconds?: number;
|
||||
};
|
||||
46
src/auto-reply/reply-payload.ts
Normal file
46
src/auto-reply/reply-payload.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import type { InteractiveReply } from "../interactive/payload.js";
|
||||
|
||||
export type ReplyPayload = {
|
||||
text?: string;
|
||||
mediaUrl?: string;
|
||||
mediaUrls?: string[];
|
||||
interactive?: InteractiveReply;
|
||||
btw?: {
|
||||
question: string;
|
||||
};
|
||||
replyToId?: string;
|
||||
replyToTag?: boolean;
|
||||
/** True when [[reply_to_current]] was present but not yet mapped to a message id. */
|
||||
replyToCurrent?: boolean;
|
||||
/** Send audio as voice message (bubble) instead of audio file. Defaults to false. */
|
||||
audioAsVoice?: boolean;
|
||||
isError?: boolean;
|
||||
/** Marks this payload as a reasoning/thinking block. Channels that do not
|
||||
* have a dedicated reasoning lane (e.g. WhatsApp, web) should suppress it. */
|
||||
isReasoning?: boolean;
|
||||
/** Marks this payload as a compaction status notice (start/end).
|
||||
* Should be excluded from TTS transcript accumulation so compaction
|
||||
* status lines are not synthesised into the spoken assistant reply. */
|
||||
isCompactionNotice?: boolean;
|
||||
/** Channel-specific payload data (per-channel envelope). */
|
||||
channelData?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type ReplyPayloadMetadata = {
|
||||
assistantMessageIndex?: number;
|
||||
};
|
||||
|
||||
const replyPayloadMetadata = new WeakMap<object, ReplyPayloadMetadata>();
|
||||
|
||||
export function setReplyPayloadMetadata<T extends object>(
|
||||
payload: T,
|
||||
metadata: ReplyPayloadMetadata,
|
||||
): T {
|
||||
const previous = replyPayloadMetadata.get(payload);
|
||||
replyPayloadMetadata.set(payload, { ...previous, ...metadata });
|
||||
return payload;
|
||||
}
|
||||
|
||||
export function getReplyPayloadMetadata(payload: object): ReplyPayloadMetadata | undefined {
|
||||
return replyPayloadMetadata.get(payload);
|
||||
}
|
||||
@@ -48,9 +48,10 @@ import {
|
||||
shouldAttemptTtsPayload,
|
||||
} from "../../tts/tts-config.js";
|
||||
import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||
import type { BlockReplyContext } from "../get-reply-options.types.js";
|
||||
import { getReplyPayloadMetadata, type ReplyPayload } from "../reply-payload.js";
|
||||
import type { FinalizedMsgContext } from "../templating.js";
|
||||
import { normalizeVerboseLevel } from "../thinking.js";
|
||||
import { getReplyPayloadMetadata, type BlockReplyContext, type ReplyPayload } from "../types.js";
|
||||
import {
|
||||
createInternalHookEvent,
|
||||
loadSessionStore,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GetReplyOptions } from "../get-reply-options.types.js";
|
||||
import type { FinalizedMsgContext } from "../templating.js";
|
||||
import type { GetReplyOptions } from "../types.js";
|
||||
import type { ReplyDispatchKind, ReplyDispatcher } from "./reply-dispatcher.types.js";
|
||||
|
||||
export type DispatchFromConfigResult = {
|
||||
|
||||
@@ -13,10 +13,11 @@ import { type OpenClawConfig, loadConfig } from "../../config/config.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { normalizeStringEntries } from "../../shared/string-normalization.js";
|
||||
import type { GetReplyOptions } from "../get-reply-options.types.js";
|
||||
import type { ReplyPayload } from "../reply-payload.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import { normalizeVerboseLevel } from "../thinking.js";
|
||||
import { SILENT_REPLY_TOKEN } from "../tokens.js";
|
||||
import type { GetReplyOptions, ReplyPayload } from "../types.js";
|
||||
import { resolveDefaultModel } from "./directive-handling.defaults.js";
|
||||
import { clearInlineDirectives } from "./get-reply-directives-utils.js";
|
||||
import { resolveReplyDirectives } from "./get-reply-directives.js";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GetReplyOptions } from "../get-reply-options.types.js";
|
||||
import type { ReplyPayload } from "../reply-payload.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import type { GetReplyOptions, ReplyPayload } from "../types.js";
|
||||
|
||||
export type GetReplyFromConfig = (
|
||||
ctx: MsgContext,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GetReplyOptions } from "../get-reply-options.types.js";
|
||||
import type { FinalizedMsgContext, MsgContext } from "../templating.js";
|
||||
import type { GetReplyOptions } from "../types.js";
|
||||
import type { DispatchFromConfigResult } from "./dispatch-from-config.types.js";
|
||||
import type { GetReplyFromConfig } from "./get-reply.types.js";
|
||||
import type {
|
||||
|
||||
@@ -1,194 +1,9 @@
|
||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
||||
import type { InteractiveReply } from "../interactive/payload.js";
|
||||
import type { PromptImageOrderEntry } from "../media/prompt-image-order.js";
|
||||
import type { TypingController } from "./reply/typing.js";
|
||||
|
||||
export type BlockReplyContext = {
|
||||
abortSignal?: AbortSignal;
|
||||
timeoutMs?: number;
|
||||
/** Source assistant message index from the upstream stream, when available. */
|
||||
assistantMessageIndex?: number;
|
||||
};
|
||||
|
||||
/** Context passed to onModelSelected callback with actual model used. */
|
||||
export type ModelSelectedContext = {
|
||||
provider: string;
|
||||
model: string;
|
||||
thinkLevel: string | undefined;
|
||||
};
|
||||
|
||||
export type TypingPolicy =
|
||||
| "auto"
|
||||
| "user_message"
|
||||
| "system_event"
|
||||
| "internal_webchat"
|
||||
| "heartbeat";
|
||||
|
||||
export type ReplyThreadingPolicy = {
|
||||
/** Override implicit reply-to-current behavior for the current turn. */
|
||||
implicitCurrentMessage?: "default" | "allow" | "deny";
|
||||
};
|
||||
|
||||
export type GetReplyOptions = {
|
||||
/** Override run id for agent events (defaults to random UUID). */
|
||||
runId?: string;
|
||||
/** Abort signal for the underlying agent run. */
|
||||
abortSignal?: AbortSignal;
|
||||
/** Optional inbound images (used for webchat attachments). */
|
||||
images?: ImageContent[];
|
||||
/** Original inline/offloaded attachment order for inbound images. */
|
||||
imageOrder?: PromptImageOrderEntry[];
|
||||
/** Notifies when an agent run actually starts (useful for webchat command handling). */
|
||||
onAgentRunStart?: (runId: string) => void;
|
||||
onReplyStart?: () => Promise<void> | void;
|
||||
/** Called when the typing controller cleans up (e.g., run ended with NO_REPLY). */
|
||||
onTypingCleanup?: () => void;
|
||||
onTypingController?: (typing: TypingController) => void;
|
||||
isHeartbeat?: boolean;
|
||||
/** Policy-level typing control for run classes (user/system/internal/heartbeat). */
|
||||
typingPolicy?: TypingPolicy;
|
||||
/** Force-disable typing indicators for this run (system/internal/cross-channel routes). */
|
||||
suppressTyping?: boolean;
|
||||
/** Resolved heartbeat model override (provider/model string from merged per-agent config). */
|
||||
heartbeatModelOverride?: string;
|
||||
/** Controls bootstrap workspace context injection (default: full). */
|
||||
bootstrapContextMode?: "full" | "lightweight";
|
||||
/** If true, suppress tool error warning payloads for this run. */
|
||||
suppressToolErrorWarnings?: boolean;
|
||||
onPartialReply?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
onReasoningStream?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
/** Called when a thinking/reasoning block ends. */
|
||||
onReasoningEnd?: () => Promise<void> | void;
|
||||
/** Called when a new assistant message starts (e.g., after tool call or thinking block). */
|
||||
onAssistantMessageStart?: () => Promise<void> | void;
|
||||
/** Called synchronously when a block reply is logically emitted, before async
|
||||
* delivery drains. Useful for channels that need to rotate preview state at
|
||||
* block boundaries without waiting for transport acks. */
|
||||
onBlockReplyQueued?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<void> | void;
|
||||
onBlockReply?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise<void> | void;
|
||||
onToolResult?: (payload: ReplyPayload) => Promise<void> | void;
|
||||
/** Called when a tool phase starts/updates, before summary payloads are emitted. */
|
||||
onToolStart?: (payload: { name?: string; phase?: string }) => Promise<void> | void;
|
||||
/** Called when a concrete work item starts, updates, or completes. */
|
||||
onItemEvent?: (payload: {
|
||||
itemId?: string;
|
||||
kind?: string;
|
||||
title?: string;
|
||||
name?: string;
|
||||
phase?: string;
|
||||
status?: string;
|
||||
summary?: string;
|
||||
progressText?: string;
|
||||
approvalId?: string;
|
||||
approvalSlug?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when the agent emits a structured plan update. */
|
||||
onPlanUpdate?: (payload: {
|
||||
phase?: string;
|
||||
title?: string;
|
||||
explanation?: string;
|
||||
steps?: string[];
|
||||
source?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when an approval becomes pending or resolves. */
|
||||
onApprovalEvent?: (payload: {
|
||||
phase?: string;
|
||||
kind?: string;
|
||||
status?: string;
|
||||
title?: string;
|
||||
itemId?: string;
|
||||
toolCallId?: string;
|
||||
approvalId?: string;
|
||||
approvalSlug?: string;
|
||||
command?: string;
|
||||
host?: string;
|
||||
reason?: string;
|
||||
message?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when command output streams or completes. */
|
||||
onCommandOutput?: (payload: {
|
||||
itemId?: string;
|
||||
phase?: string;
|
||||
title?: string;
|
||||
toolCallId?: string;
|
||||
name?: string;
|
||||
output?: string;
|
||||
status?: string;
|
||||
exitCode?: number | null;
|
||||
durationMs?: number;
|
||||
cwd?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when a patch completes with a file summary. */
|
||||
onPatchSummary?: (payload: {
|
||||
itemId?: string;
|
||||
phase?: string;
|
||||
title?: string;
|
||||
toolCallId?: string;
|
||||
name?: string;
|
||||
added?: string[];
|
||||
modified?: string[];
|
||||
deleted?: string[];
|
||||
summary?: string;
|
||||
}) => Promise<void> | void;
|
||||
/** Called when context auto-compaction starts (allows UX feedback during the pause). */
|
||||
onCompactionStart?: () => Promise<void> | void;
|
||||
/** Called when context auto-compaction completes. */
|
||||
onCompactionEnd?: () => Promise<void> | void;
|
||||
/** Called when the actual model is selected (including after fallback).
|
||||
* Use this to get model/provider/thinkLevel for responsePrefix template interpolation. */
|
||||
onModelSelected?: (ctx: ModelSelectedContext) => void;
|
||||
disableBlockStreaming?: boolean;
|
||||
/** Timeout for block reply delivery (ms). */
|
||||
blockReplyTimeoutMs?: number;
|
||||
/** If provided, only load these skills for this session (empty = no skills). */
|
||||
skillFilter?: string[];
|
||||
/** Mutable ref to track if a reply was sent (for Slack "first" threading mode). */
|
||||
hasRepliedRef?: { value: boolean };
|
||||
/** Override agent timeout in seconds (0 = no timeout). Threads through to resolveAgentTimeoutMs. */
|
||||
timeoutOverrideSeconds?: number;
|
||||
};
|
||||
|
||||
export type ReplyPayload = {
|
||||
text?: string;
|
||||
mediaUrl?: string;
|
||||
mediaUrls?: string[];
|
||||
interactive?: InteractiveReply;
|
||||
btw?: {
|
||||
question: string;
|
||||
};
|
||||
replyToId?: string;
|
||||
replyToTag?: boolean;
|
||||
/** True when [[reply_to_current]] was present but not yet mapped to a message id. */
|
||||
replyToCurrent?: boolean;
|
||||
/** Send audio as voice message (bubble) instead of audio file. Defaults to false. */
|
||||
audioAsVoice?: boolean;
|
||||
isError?: boolean;
|
||||
/** Marks this payload as a reasoning/thinking block. Channels that do not
|
||||
* have a dedicated reasoning lane (e.g. WhatsApp, web) should suppress it. */
|
||||
isReasoning?: boolean;
|
||||
/** Marks this payload as a compaction status notice (start/end).
|
||||
* Should be excluded from TTS transcript accumulation so compaction
|
||||
* status lines are not synthesised into the spoken assistant reply. */
|
||||
isCompactionNotice?: boolean;
|
||||
/** Channel-specific payload data (per-channel envelope). */
|
||||
channelData?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type ReplyPayloadMetadata = {
|
||||
assistantMessageIndex?: number;
|
||||
};
|
||||
|
||||
const replyPayloadMetadata = new WeakMap<object, ReplyPayloadMetadata>();
|
||||
|
||||
export function setReplyPayloadMetadata<T extends object>(
|
||||
payload: T,
|
||||
metadata: ReplyPayloadMetadata,
|
||||
): T {
|
||||
const previous = replyPayloadMetadata.get(payload);
|
||||
replyPayloadMetadata.set(payload, { ...previous, ...metadata });
|
||||
return payload;
|
||||
}
|
||||
|
||||
export function getReplyPayloadMetadata(payload: object): ReplyPayloadMetadata | undefined {
|
||||
return replyPayloadMetadata.get(payload);
|
||||
}
|
||||
export type {
|
||||
BlockReplyContext,
|
||||
GetReplyOptions,
|
||||
ModelSelectedContext,
|
||||
ReplyThreadingPolicy,
|
||||
TypingPolicy,
|
||||
} from "./get-reply-options.types.js";
|
||||
export { getReplyPayloadMetadata, setReplyPayloadMetadata } from "./reply-payload.js";
|
||||
export type { ReplyPayload, ReplyPayloadMetadata } from "./reply-payload.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { getChannelPlugin, normalizeChannelId } from "./registry.js";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { OutboundDeliveryResult } from "../../infra/outbound/deliver-types.js";
|
||||
import type { OutboundIdentity } from "../../infra/outbound/identity-types.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import type { LegacyConfigRule } from "../../config/legacy.shared.js";
|
||||
import type { AgentBinding } from "../../config/types.agents.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core";
|
||||
import type { TSchema } from "@sinclair/typebox";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import type { MsgContext } from "../../auto-reply/templating.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { MarkdownTableMode } from "../../config/types.base.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GatewayClientMode, GatewayClientName } from "../../gateway/protocol/client-info.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { resolveAgentIdentity, resolveEffectiveMessagesConfig } from "../agents/identity.js";
|
||||
import type { GetReplyOptions } from "../auto-reply/get-reply-options.types.js";
|
||||
import {
|
||||
extractShortModelName,
|
||||
type ResponsePrefixContext,
|
||||
} from "../auto-reply/reply/response-prefix-template.js";
|
||||
import type { GetReplyOptions } from "../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { countActiveDescendantRuns } from "../../agents/subagent-registry-read.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { CliDeps } from "../../cli/outbound-send-deps.js";
|
||||
import {
|
||||
resolveAgentMainSessionKey,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { hasOutboundReplyContent } from "openclaw/plugin-sdk/reply-payload";
|
||||
import { DEFAULT_HEARTBEAT_ACK_MAX_CHARS } from "../../auto-reply/heartbeat.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import { truncateUtf16Safe } from "../../utils.js";
|
||||
import { shouldSkipHeartbeatOnlyDelivery } from "../heartbeat-policy.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import { isAudioFileName } from "../../media/mime.js";
|
||||
import { resolveSendableOutboundReplyParts } from "../../plugin-sdk/reply-payload.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
@@ -7,9 +7,9 @@ import { resolveThinkingDefault } from "../../agents/model-selection.js";
|
||||
import { rewriteTranscriptEntriesInSessionFile } from "../../agents/pi-embedded-runner/transcript-rewrite.js";
|
||||
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
||||
import { dispatchInboundMessage } from "../../auto-reply/dispatch.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
import { createReplyDispatcher } from "../../auto-reply/reply/reply-dispatcher.js";
|
||||
import type { MsgContext } from "../../auto-reply/templating.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||
import { extractCanvasFromText } from "../../chat/canvas-render.js";
|
||||
import { resolveSessionFilePath } from "../../config/sessions.js";
|
||||
import { jsonUtf8Bytes } from "../../infra/json-utf8-bytes.js";
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
|
||||
import type { GetReplyOptions } from "../auto-reply/types.js";
|
||||
import type { GetReplyOptions } from "../auto-reply/get-reply-options.types.js";
|
||||
import { clearConfigCache } from "../config/config.js";
|
||||
import { __setMaxChatHistoryMessagesBytesForTest } from "./server-constants.js";
|
||||
import {
|
||||
|
||||
@@ -2,8 +2,9 @@ import crypto from "node:crypto";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { Mock, vi } from "vitest";
|
||||
import type { GetReplyOptions } from "../auto-reply/get-reply-options.types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type { MsgContext } from "../auto-reply/templating.js";
|
||||
import type { GetReplyOptions, ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { AgentBinding } from "../config/types.agents.js";
|
||||
import type { HooksConfig } from "../config/types.hooks.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type { ExecApprovalForwardTarget } from "../config/types.approvals.js";
|
||||
import { matchesApprovalRequestFilters } from "../infra/approval-request-filters.js";
|
||||
import { getExecApprovalReplyMetadata } from "../infra/exec-approval-reply.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import {
|
||||
buildApprovalInteractiveReply,
|
||||
type ExecApprovalReplyDecision,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import { getChannelPlugin, normalizeChannelId } from "../channels/plugins/index.js";
|
||||
import {
|
||||
createReplyPrefixContext,
|
||||
|
||||
@@ -99,7 +99,7 @@ export type {
|
||||
export type { OpenClawConfig } from "../config/config.js";
|
||||
export type { OutboundIdentity } from "../infra/outbound/identity.js";
|
||||
export type { HistoryEntry } from "../auto-reply/reply/history.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export type { AllowlistMatch } from "../channels/allowlist-match.js";
|
||||
export type {
|
||||
BaseProbeResult,
|
||||
|
||||
@@ -8,7 +8,7 @@ export {
|
||||
DEFAULT_GROUP_HISTORY_LIMIT,
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
} from "../auto-reply/reply/history.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { logTypingFailure } from "../channels/logging.js";
|
||||
export type { AllowlistMatch } from "../channels/plugins/allowlist-match.js";
|
||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { withReplyDispatcher } from "../auto-reply/dispatch.js";
|
||||
import type { GetReplyOptions } from "../auto-reply/get-reply-options.types.js";
|
||||
import {
|
||||
dispatchReplyFromConfig,
|
||||
type DispatchFromConfigResult,
|
||||
@@ -6,7 +7,6 @@ import {
|
||||
import type { DispatchReplyWithBufferedBlockDispatcher } from "../auto-reply/reply/provider-dispatcher.types.js";
|
||||
import type { ReplyDispatcher } from "../auto-reply/reply/reply-dispatcher.types.js";
|
||||
import type { FinalizedMsgContext } from "../auto-reply/templating.js";
|
||||
import type { GetReplyOptions } from "../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { createChannelReplyPipeline } from "./channel-reply-pipeline.js";
|
||||
import { createNormalizedOutboundDeliverer, type OutboundReplyPayload } from "./reply-payload.js";
|
||||
|
||||
@@ -90,7 +90,7 @@ export * from "./music-generation.js";
|
||||
export type { SecretInput, SecretRef } from "../config/types.secrets.js";
|
||||
export type { RuntimeEnv } from "../runtime.js";
|
||||
export type { HookEntry } from "../hooks/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export type { WizardPrompter } from "../wizard/prompts.js";
|
||||
export type { ContextEngineFactory } from "../context-engine/registry.js";
|
||||
export type { DiagnosticEventPayload } from "../infra/diagnostic-events.js";
|
||||
|
||||
@@ -5,7 +5,7 @@ export type {
|
||||
} from "../channels/plugins/types.public.js";
|
||||
export type { ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
||||
export type { OpenClawConfig } from "../config/config.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js";
|
||||
export type { OpenClawPluginApi, PluginRuntime } from "./channel-plugin-common.js";
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ export {
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "../agents/tools/common.js";
|
||||
export type { BlockReplyContext, ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { BlockReplyContext } from "../auto-reply/get-reply-options.types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { resolveAckReaction } from "../agents/identity.js";
|
||||
export {
|
||||
compileAllowlist,
|
||||
|
||||
@@ -10,7 +10,7 @@ export {
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
} from "../auto-reply/reply/history.js";
|
||||
export { listSkillCommandsForAgents } from "../auto-reply/skill-commands.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export type { ChatType } from "../channels/chat-type.js";
|
||||
export { resolveControlCommandGate } from "../channels/command-gating.js";
|
||||
export { logInboundDrop, logTypingFailure } from "../channels/logging.js";
|
||||
|
||||
@@ -12,7 +12,7 @@ export {
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
} from "../auto-reply/reply/history.js";
|
||||
export { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { mergeAllowlist, summarizeMapping } from "../channels/allowlists/resolve-utils.js";
|
||||
export {
|
||||
resolveControlCommandGate,
|
||||
|
||||
@@ -7,4 +7,4 @@ export {
|
||||
} from "../auto-reply/chunk.js";
|
||||
export type { ChunkMode } from "../auto-reply/chunk.js";
|
||||
export { isSilentReplyText } from "../auto-reply/tokens.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
|
||||
@@ -4,4 +4,4 @@ export {
|
||||
dispatchReplyWithBufferedBlockDispatcher,
|
||||
dispatchReplyWithDispatcher,
|
||||
} from "../auto-reply/reply/provider-dispatcher.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { readStringValue } from "../shared/string-coerce.js";
|
||||
|
||||
export type { MediaPayload, MediaPayloadInput } from "../channels/plugins/media-payload.js";
|
||||
export { buildMediaPayload } from "../channels/plugins/media-payload.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
|
||||
export type OutboundReplyPayload = {
|
||||
text?: string;
|
||||
|
||||
@@ -3,4 +3,4 @@ export {
|
||||
isSingleUseReplyToMode,
|
||||
} from "../auto-reply/reply/reply-reference.js";
|
||||
export { resolveBatchedReplyThreadingPolicy } from "../auto-reply/reply/reply-threading.js";
|
||||
export type { ReplyThreadingPolicy } from "../auto-reply/types.js";
|
||||
export type { ReplyThreadingPolicy } from "../auto-reply/get-reply-options.types.js";
|
||||
|
||||
@@ -53,8 +53,8 @@ export type {
|
||||
ReplyDispatcherWithTypingOptions,
|
||||
} from "../auto-reply/reply/reply-dispatcher.js";
|
||||
export { createReplyReferencePlanner } from "../auto-reply/reply/reply-reference.js";
|
||||
export type { GetReplyOptions, ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { BlockReplyContext } from "../auto-reply/types.js";
|
||||
export type { GetReplyOptions, BlockReplyContext } from "../auto-reply/get-reply-options.types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export type { FinalizedMsgContext, MsgContext } from "../auto-reply/templating.js";
|
||||
export { generateConversationLabel } from "../auto-reply/reply/conversation-label-generator.js";
|
||||
export type { ConversationLabelParams } from "../auto-reply/reply/conversation-label-generator.js";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { createOptionalChannelSetupSurface } from "./channel-setup.js";
|
||||
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||
export {
|
||||
applyAccountNameToChannelSection,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { createOptionalChannelSetupSurface } from "./channel-setup.js";
|
||||
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||
export type {
|
||||
ChannelGatewayContext,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Keep this list additive and scoped to the bundled Zalo surface.
|
||||
|
||||
export { jsonResult, readStringParam } from "../agents/tools/common.js";
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export {
|
||||
deleteAccountFromConfigSection,
|
||||
setAccountEnabledInConfigSection,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { createOptionalChannelSetupSurface } from "./channel-setup.js";
|
||||
|
||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||
export type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
export { mergeAllowlist, summarizeMapping } from "../channels/allowlists/resolve-utils.js";
|
||||
export {
|
||||
resolveMentionGating,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import {
|
||||
createConversationBindingRecord,
|
||||
resolveConversationBindingRecord,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
|
||||
export type PluginConversationBindingRequestParams = {
|
||||
summary?: string;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type {
|
||||
ReplyDispatchKind,
|
||||
ReplyDispatcher,
|
||||
} from "../auto-reply/reply/reply-dispatcher.types.js";
|
||||
import type { FinalizedMsgContext } from "../auto-reply/templating.js";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { TtsAutoMode } from "../config/types.tts.js";
|
||||
import {
|
||||
|
||||
@@ -17,8 +17,8 @@ import type { ModelProviderRequestTransportOverrides } from "../agents/provider-
|
||||
import type { ProviderSystemPromptContribution } from "../agents/system-prompt-contribution.js";
|
||||
import type { PromptMode } from "../agents/system-prompt.types.js";
|
||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
import type { ThinkLevel } from "../auto-reply/thinking.shared.js";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
||||
import type { ChannelId } from "../channels/plugins/types.public.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
|
||||
Reference in New Issue
Block a user