From d9d4514c00b549fac8ed3f2bb8913ffefd5d53c0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 3 Jun 2026 19:31:07 -0400 Subject: [PATCH] docs: document auto-reply directive helpers --- src/auto-reply/reply/commands-subagents.test-helpers.ts | 1 + src/auto-reply/reply/current-turn-images.ts | 3 +++ src/auto-reply/reply/directive-handling.parse.ts | 3 +++ src/auto-reply/reply/get-reply-directives-utils.ts | 2 ++ src/auto-reply/reply/history.types.ts | 2 ++ src/auto-reply/reply/model-selection-directive.ts | 6 ++++++ 6 files changed, 17 insertions(+) diff --git a/src/auto-reply/reply/commands-subagents.test-helpers.ts b/src/auto-reply/reply/commands-subagents.test-helpers.ts index e6e60bf960b9..8882c8bab1b1 100644 --- a/src/auto-reply/reply/commands-subagents.test-helpers.ts +++ b/src/auto-reply/reply/commands-subagents.test-helpers.ts @@ -1,5 +1,6 @@ import type { InlineDirectives } from "./directive-handling.js"; +/** Test helper that returns a fully cleared inline-directive object. */ export function createEmptyInlineDirectives(): InlineDirectives { return { cleaned: "", diff --git a/src/auto-reply/reply/current-turn-images.ts b/src/auto-reply/reply/current-turn-images.ts index 8d6d361418b9..408982703f16 100644 --- a/src/auto-reply/reply/current-turn-images.ts +++ b/src/auto-reply/reply/current-turn-images.ts @@ -22,6 +22,7 @@ function isGenericMediaType(mediaType: string | undefined): boolean { return normalized === "application/octet-stream" || normalized === "binary/octet-stream"; } +/** Resolves image media types from current-turn attachment metadata or filenames. */ function resolveCurrentImageMediaType(pathValue: unknown, mediaType?: unknown): string | undefined { const mediaPath = normalizeOptionalString(pathValue); if (!mediaPath) { @@ -86,6 +87,7 @@ function createUndescribedImageContext( }; } +/** Resolves current-turn image attachments that were not already described by media understanding. */ export async function resolveCurrentTurnImages(params: { ctx: MsgContext; cfg: OpenClawConfig; @@ -112,6 +114,7 @@ export async function resolveCurrentTurnImages(params: { } try { + // Only send undescribed current images natively; described images already exist as text context. const resolved = await resolveAgentTurnAttachments({ ctx: createUndescribedImageContext(params.ctx, undescribedImageAttachments), cfg: params.cfg, diff --git a/src/auto-reply/reply/directive-handling.parse.ts b/src/auto-reply/reply/directive-handling.parse.ts index 6346b5b0e9ab..deb9be45b47e 100644 --- a/src/auto-reply/reply/directive-handling.parse.ts +++ b/src/auto-reply/reply/directive-handling.parse.ts @@ -21,6 +21,7 @@ import { import { extractQueueDirective } from "./queue/directive.js"; import type { QueueDropPolicy, QueueMode } from "./queue/types.js"; +/** Parsed inline directives removed from a user message before agent execution. */ export type InlineDirectives = { cleaned: string; hasThinkDirective: boolean; @@ -75,6 +76,7 @@ export type InlineDirectives = { hasQueueOptions: boolean; }; +/** Parses supported inline directives in the same order they are stripped from text. */ export function parseInlineDirectives( body: string, options?: { @@ -171,6 +173,7 @@ export function parseInlineDirectives( hasOptions: hasQueueOptions, } = extractQueueDirective(modelCleaned); + // Later directives see text cleaned by earlier directives; preserve that ordering. return { cleaned: queueCleaned, hasThinkDirective, diff --git a/src/auto-reply/reply/get-reply-directives-utils.ts b/src/auto-reply/reply/get-reply-directives-utils.ts index f588bf31d9aa..f93d9956ddbb 100644 --- a/src/auto-reply/reply/get-reply-directives-utils.ts +++ b/src/auto-reply/reply/get-reply-directives-utils.ts @@ -17,6 +17,7 @@ const CLEARED_EXEC_FIELDS = { invalidExecNode: false, } satisfies Partial; +/** Clears all inline directive state while preserving cleaned text. */ export function clearInlineDirectives(cleaned: string): InlineDirectives { return { cleaned, @@ -58,6 +59,7 @@ export function clearInlineDirectives(cleaned: string): InlineDirectives { }; } +/** Clears only exec-related directive state after execution policy is consumed. */ export function clearExecInlineDirectives(directives: InlineDirectives): InlineDirectives { return { ...directives, diff --git a/src/auto-reply/reply/history.types.ts b/src/auto-reply/reply/history.types.ts index 0e541365d051..1632a25b8e39 100644 --- a/src/auto-reply/reply/history.types.ts +++ b/src/auto-reply/reply/history.types.ts @@ -1,3 +1,4 @@ +/** Normalized history message used when building reply context. */ export type HistoryEntry = { sender: string; body: string; @@ -6,6 +7,7 @@ export type HistoryEntry = { media?: HistoryMediaEntry[]; }; +/** Media metadata attached to a normalized history message. */ export type HistoryMediaEntry = { path?: string; url?: string; diff --git a/src/auto-reply/reply/model-selection-directive.ts b/src/auto-reply/reply/model-selection-directive.ts index 2678044af6d5..bc24f1bf98a8 100644 --- a/src/auto-reply/reply/model-selection-directive.ts +++ b/src/auto-reply/reply/model-selection-directive.ts @@ -3,6 +3,7 @@ import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/st import { splitTrailingAuthProfile } from "../../agents/model-ref-profile.js"; import { isModelKeyAllowedBySet } from "../../agents/model-selection-shared.js"; +/** Alias lookup tables used by `/model` directive resolution. */ export type ModelAliasIndex = { byAlias: Map< string, @@ -14,6 +15,7 @@ export type ModelAliasIndex = { byKey: Map; }; +/** Resolved model choice from a `/model` directive. */ export type ModelDirectiveSelection = { provider: string; model: string; @@ -56,6 +58,7 @@ const FUZZY_VARIANT_TOKENS = [ "nano", ]; +/** Builds the canonical provider/model key used by allowlists and aliases. */ export function modelKey(provider: string, model: string): string { const providerId = provider.trim(); const modelId = model.trim(); @@ -72,6 +75,7 @@ export function modelKey(provider: string, model: string): string { : `${providerId}/${modelId}`; } +/** Resolves an explicit model directive string into a provider/model ref. */ export function resolveModelRefFromDirectiveString(params: { raw: string; defaultProvider: string; @@ -260,6 +264,7 @@ function scoreFuzzyMatch(params: { }; } +/** Resolves a `/model` directive into an allowlisted model selection or error. */ export function resolveModelDirectiveSelection(params: { raw: string; defaultProvider: string; @@ -356,6 +361,7 @@ export function resolveModelDirectiveSelection(params: { return Object.assign({ candidate }, details); }) .toSorted((a, b) => { + // Tie-break deterministically so repeated prompts pick the same model. if (b.score !== a.score) { return b.score - a.score; }