mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
docs: document auto reply routing helpers
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
/** Formats and appends token/cost usage lines to reply payloads. */
|
||||
import {
|
||||
estimateUsageCost,
|
||||
formatTokenCount,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Resolves channel and account context for command handlers. */
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
@@ -30,6 +31,7 @@ type ChannelAccountParams = {
|
||||
};
|
||||
};
|
||||
|
||||
/** Resolves the command surface channel from inbound context and command state. */
|
||||
export function resolveCommandSurfaceChannel(params: CommandSurfaceParams): string {
|
||||
const channel =
|
||||
params.ctx.OriginatingChannel ??
|
||||
@@ -39,6 +41,7 @@ export function resolveCommandSurfaceChannel(params: CommandSurfaceParams): stri
|
||||
return normalizeOptionalLowercaseString(channel) ?? "";
|
||||
}
|
||||
|
||||
/** Resolves command account id, falling back to plugin default account config. */
|
||||
export function resolveChannelAccountId(params: ChannelAccountParams): string {
|
||||
const accountId = normalizeOptionalString(params.ctx.AccountId) ?? "";
|
||||
if (accountId) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Handles diagnostics commands and private owner routing for sensitive diagnostics output. */
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
||||
import { createExecTool } from "../../agents/bash-tools.js";
|
||||
@@ -58,6 +59,7 @@ const defaultDiagnosticsCommandDeps: DiagnosticsCommandDeps = {
|
||||
deliverPrivateDiagnosticsReply,
|
||||
};
|
||||
|
||||
/** Creates a diagnostics command handler with injectable private-route dependencies. */
|
||||
export function createDiagnosticsCommandHandler(
|
||||
deps: Partial<DiagnosticsCommandDeps> = {},
|
||||
): CommandHandler {
|
||||
@@ -69,6 +71,7 @@ export function createDiagnosticsCommandHandler(
|
||||
await handleDiagnosticsCommandWithDeps(resolvedDeps, params, allowTextCommands);
|
||||
}
|
||||
|
||||
/** Default diagnostics command handler. */
|
||||
export const handleDiagnosticsCommand: CommandHandler = createDiagnosticsCommandHandler();
|
||||
|
||||
async function handleDiagnosticsCommandWithDeps(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Private command reply routing for sensitive owner-only command output. */
|
||||
import { resolveExpiresAtMsFromDurationMs } from "@openclaw/normalization-core/number-coercion";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
@@ -14,6 +15,7 @@ import type { ReplyPayload } from "../types.js";
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
import { routeReply } from "./route-reply.js";
|
||||
|
||||
/** Resolved private delivery target for command replies and approvals. */
|
||||
export type PrivateCommandRouteTarget = {
|
||||
channel: string;
|
||||
to: string;
|
||||
@@ -24,6 +26,7 @@ export type PrivateCommandRouteTarget = {
|
||||
const PRIVATE_COMMAND_APPROVAL_ROUTE_TTL_MS = 5 * 60_000;
|
||||
const EXPIRED_PRIVATE_COMMAND_APPROVAL_ROUTE_EXPIRES_AT_MS = 0;
|
||||
|
||||
/** Resolves expiry timestamp for temporary private approval routes. */
|
||||
export function resolvePrivateCommandApprovalRouteExpiresAtMs(nowMs = Date.now()): number {
|
||||
return (
|
||||
resolveExpiresAtMsFromDurationMs(PRIVATE_COMMAND_APPROVAL_ROUTE_TTL_MS, { nowMs }) ??
|
||||
@@ -31,6 +34,7 @@ export function resolvePrivateCommandApprovalRouteExpiresAtMs(nowMs = Date.now()
|
||||
);
|
||||
}
|
||||
|
||||
/** Finds private owner DM routes that can receive sensitive command replies. */
|
||||
export async function resolvePrivateCommandRouteTargets(params: {
|
||||
commandParams: HandleCommandsParams;
|
||||
request: ExecApprovalRequest;
|
||||
@@ -80,6 +84,7 @@ export async function resolvePrivateCommandRouteTargets(params: {
|
||||
});
|
||||
}
|
||||
|
||||
/** Delivers a sensitive command reply to the resolved private targets. */
|
||||
export async function deliverPrivateCommandReply(params: {
|
||||
commandParams: HandleCommandsParams;
|
||||
targets: PrivateCommandRouteTarget[];
|
||||
@@ -105,6 +110,7 @@ export async function deliverPrivateCommandReply(params: {
|
||||
return results.some((result) => result.status === "fulfilled" && result.value.ok);
|
||||
}
|
||||
|
||||
/** Reads the command message thread id from command context. */
|
||||
export function readCommandMessageThreadId(params: HandleCommandsParams): string | undefined {
|
||||
return typeof params.ctx.MessageThreadId === "string" ||
|
||||
typeof params.ctx.MessageThreadId === "number"
|
||||
@@ -112,6 +118,7 @@ export function readCommandMessageThreadId(params: HandleCommandsParams): string
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/** Reads the best delivery target for command route resolution. */
|
||||
export function readCommandDeliveryTarget(params: HandleCommandsParams): string | undefined {
|
||||
return (
|
||||
normalizeOptionalString(params.ctx.OriginatingTo) ??
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Builds /status replies using the command's authorized channel context. */
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { buildStatusText } from "../../status/status-text.js";
|
||||
import type { BuildStatusTextParams } from "../../status/status-text.types.js";
|
||||
@@ -9,6 +10,7 @@ type BuildStatusReplyParams = Omit<BuildStatusTextParams, "statusChannel"> & {
|
||||
command: CommandContext;
|
||||
};
|
||||
|
||||
/** Builds a status reply or suppresses unauthorized status requests. */
|
||||
export async function buildStatusReply(
|
||||
params: BuildStatusReplyParams,
|
||||
): Promise<ReplyPayload | undefined> {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Text extraction helpers for subagent command output. */
|
||||
import { sanitizeTextContent } from "../../agents/tools/chat-history-text.js";
|
||||
import { extractTextFromChatContent } from "../../shared/chat-content.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Resolves /model directive selections and auth profile overrides. */
|
||||
import { ensureAuthProfileStore } from "../../agents/auth-profiles.js";
|
||||
import { isModelKeyAllowedBySet } from "../../agents/model-selection-shared.js";
|
||||
import {
|
||||
@@ -44,6 +45,7 @@ function resolveStoredNumericProfileModelDirective(params: { raw: string; agentD
|
||||
return { modelRaw, profileId, profileProvider: profile.provider };
|
||||
}
|
||||
|
||||
/** Resolves the requested model/profile override from parsed inline directives. */
|
||||
export function resolveModelSelectionFromDirective(params: {
|
||||
directives: InlineDirectives;
|
||||
cfg: OpenClawConfig;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Validation and status handling for /queue directives. */
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
/** Resolves the effective reply route from current context and persisted session route. */
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import { stringifyRouteThreadId } from "../../plugin-sdk/channel-route.js";
|
||||
import type { InputProvenance } from "../../sessions/input-provenance.js";
|
||||
import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||
import type { FinalizedMsgContext } from "../templating.js";
|
||||
|
||||
/** Current finalized context fields used for reply route resolution. */
|
||||
export type EffectiveReplyRouteContext = Pick<
|
||||
FinalizedMsgContext,
|
||||
"Provider" | "Surface" | "OriginatingChannel" | "OriginatingTo" | "AccountId" | "InputProvenance"
|
||||
>;
|
||||
|
||||
/** Persisted session fields used as route fallback/inheritance. */
|
||||
export type EffectiveReplyRouteEntry = Pick<
|
||||
SessionEntry,
|
||||
"deliveryContext" | "lastChannel" | "lastTo" | "lastAccountId" | "route"
|
||||
>;
|
||||
|
||||
/** Effective channel target selected for source reply delivery. */
|
||||
export type EffectiveReplyRoute = {
|
||||
channel?: string;
|
||||
to?: string;
|
||||
@@ -22,6 +26,7 @@ export type EffectiveReplyRoute = {
|
||||
inheritedExternalRoute?: boolean;
|
||||
};
|
||||
|
||||
/** Returns true for synthetic providers that should not define a user channel route. */
|
||||
export function isSystemEventProvider(provider?: string): boolean {
|
||||
return provider === "heartbeat" || provider === "cron-event" || provider === "exec-event";
|
||||
}
|
||||
@@ -53,6 +58,7 @@ function resolveTrustedInheritedThreadId(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Resolves current, inherited, or persisted reply route for a session turn. */
|
||||
export function resolveEffectiveReplyRoute(params: {
|
||||
ctx: EffectiveReplyRouteContext;
|
||||
entry?: EffectiveReplyRouteEntry;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Prepares queued follow-up payloads for source-channel delivery. */
|
||||
import type { MessagingToolSend } from "../../agents/embedded-agent-messaging.types.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { stripHeartbeatToken } from "../heartbeat.js";
|
||||
@@ -23,6 +24,7 @@ function hasReplyPayloadMedia(payload: ReplyPayload): boolean {
|
||||
return Array.isArray(payload.mediaUrls) && payload.mediaUrls.some((url) => url.trim().length > 0);
|
||||
}
|
||||
|
||||
/** Strips heartbeat tokens, applies threading, and dedupes message-tool sends. */
|
||||
export function resolveFollowupDeliveryPayloads(params: {
|
||||
cfg: OpenClawConfig;
|
||||
payloads: ReplyPayload[];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Handles inline slash commands, skill invocations, and abort actions before model runs. */
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
@@ -120,6 +121,7 @@ function isMentionOnlyResidualText(text: string, wasMentioned: boolean | undefin
|
||||
return /^(?:<@[!&]?[A-Za-z0-9._:-]+>|<!(?:here|channel|everyone)>|[:,.!?-]|\s)+$/u.test(trimmed);
|
||||
}
|
||||
|
||||
/** Result of attempting to handle an inbound message as an inline action. */
|
||||
export type InlineActionResult =
|
||||
| { kind: "reply"; reply: ReplyPayload | ReplyPayload[] | undefined }
|
||||
| {
|
||||
@@ -177,6 +179,7 @@ function extractBlockedToolReason(result: unknown): string | null {
|
||||
return typeof reason === "string" && reason.trim() ? reason.trim() : null;
|
||||
}
|
||||
|
||||
/** Handles inline actions or returns continue when the message should become a model turn. */
|
||||
export async function handleInlineActions(params: {
|
||||
ctx: MsgContext;
|
||||
sessionCtx: TemplateContext;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Lightweight reply-stage profiler for slow-turn diagnostics. */
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { isDiagnosticFlagEnabled } from "../../infra/diagnostic-flags.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Resolves runtime policy session keys distinct from transcript session keys. */
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
@@ -84,6 +85,7 @@ function isMainSessionAlias(params: {
|
||||
}
|
||||
|
||||
/** Resolves the session key used for runtime policy checks and direct-message scoping. */
|
||||
/** Resolves the session key used for sandbox/tool/runtime policy lookups. */
|
||||
export function resolveRuntimePolicySessionKey(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
ctx?: RuntimePolicyContext;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Public session-fork facade with parent-size admission checks. */
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import { createLazyImportLoader } from "../../shared/lazy-promise.js";
|
||||
|
||||
@@ -9,6 +10,7 @@ import { createLazyImportLoader } from "../../shared/lazy-promise.js";
|
||||
const DEFAULT_PARENT_FORK_MAX_TOKENS = 100_000;
|
||||
const sessionForkRuntimeLoader = createLazyImportLoader(() => import("./session-fork.runtime.js"));
|
||||
|
||||
/** Decision for whether a child session should fork parent context or start isolated. */
|
||||
export type ParentForkDecision =
|
||||
| {
|
||||
status: "fork";
|
||||
@@ -37,6 +39,7 @@ function formatParentForkTooLargeMessage(params: {
|
||||
);
|
||||
}
|
||||
|
||||
/** Decides whether parent context is small enough to fork into a child session. */
|
||||
export async function resolveParentForkDecision(params: {
|
||||
parentEntry: SessionEntry;
|
||||
storePath: string;
|
||||
@@ -62,6 +65,7 @@ export async function resolveParentForkDecision(params: {
|
||||
};
|
||||
}
|
||||
|
||||
/** Forks a new session transcript from a parent session. */
|
||||
export async function forkSessionFromParent(params: {
|
||||
parentEntry: SessionEntry;
|
||||
agentId: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Clears reset-related queues and system events for session keys. */
|
||||
import { drainSystemEventEntries } from "../../infra/system-events.js";
|
||||
import { clearSessionQueues, type ClearSessionQueueResult } from "./queue/cleanup.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** Persists usage, cost, model, and CLI session metadata after reply runs. */
|
||||
import {
|
||||
clearCliSession,
|
||||
setCliSessionBinding,
|
||||
@@ -92,6 +93,7 @@ function estimateSessionRunCostUsd(params: {
|
||||
return resolveNonNegativeNumber(estimateUsageCost({ usage: params.usage, cost }));
|
||||
}
|
||||
|
||||
/** Persists usage accounting and selected runtime metadata to the session store. */
|
||||
export async function persistSessionUsageUpdate(params: {
|
||||
storePath?: string;
|
||||
sessionKey?: string;
|
||||
|
||||
Reference in New Issue
Block a user