mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 11:25:50 -06:00
docs: document embedded agent helpers
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Splits streamed embedded-agent replies into Markdown-safe message chunks.
|
||||
*/
|
||||
import type { FenceSpan } from "../../packages/markdown-core/src/fences.js";
|
||||
import {
|
||||
findFenceSpanAt,
|
||||
@@ -116,6 +119,7 @@ export class EmbeddedBlockChunker {
|
||||
this.#chunking = chunking;
|
||||
}
|
||||
|
||||
/** Add streamed text to the pending chunk buffer. */
|
||||
append(text: string) {
|
||||
if (!text) {
|
||||
return;
|
||||
@@ -123,18 +127,22 @@ export class EmbeddedBlockChunker {
|
||||
this.#buffer += text;
|
||||
}
|
||||
|
||||
/** Clear any buffered reply text without emitting it. */
|
||||
reset() {
|
||||
this.#buffer = "";
|
||||
}
|
||||
|
||||
/** Return the currently buffered text for tests and flush logic. */
|
||||
get bufferedText() {
|
||||
return this.#buffer;
|
||||
}
|
||||
|
||||
/** Return true when there is pending text to drain. */
|
||||
hasBuffered(): boolean {
|
||||
return this.#buffer.length > 0;
|
||||
}
|
||||
|
||||
/** Emit safe chunks according to size and Markdown fence constraints. */
|
||||
drain(params: { force: boolean; emit: (chunk: string) => void }) {
|
||||
// KNOWN: We cannot split inside fenced code blocks (Markdown breaks + UI glitches).
|
||||
// When forced (maxChars), we close + reopen the fence to keep Markdown valid.
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Builds structured observations for embedded-agent API/text failures.
|
||||
*/
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { readLoggingConfig } from "../logging/config.js";
|
||||
import { redactIdentifier } from "../logging/redact-identifier.js";
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Builds and sanitizes bootstrap context inserted into embedded-agent sessions.
|
||||
*/
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Classifies provider/runtime failures and formats assistant-facing error text.
|
||||
*/
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
@@ -75,6 +78,7 @@ export const GENERIC_ASSISTANT_ERROR_TEXT = "LLM request failed.";
|
||||
const PROVIDER_SCHEMA_REJECTION_USER_TEXT =
|
||||
"LLM request failed: provider rejected the request schema or tool payload.";
|
||||
|
||||
/** Detect provider errors that require reasoning to stay enabled. */
|
||||
export function isReasoningConstraintErrorMessage(raw: string): boolean {
|
||||
if (!raw) {
|
||||
return false;
|
||||
@@ -93,6 +97,7 @@ function hasRateLimitTpmHint(raw: string): boolean {
|
||||
return /\btpm\b/i.test(lower) || lower.includes("tokens per minute");
|
||||
}
|
||||
|
||||
/** Detect explicit context-window overflow without confusing TPM rate limits. */
|
||||
export function isContextOverflowError(errorMessage?: string): boolean {
|
||||
if (!errorMessage) {
|
||||
return false;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Shared text-pattern matchers for failover, auth, billing, and rate-limit errors.
|
||||
*/
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
|
||||
type ErrorPattern = RegExp | string;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Google/Gemini-specific embedded-agent runtime helpers.
|
||||
*/
|
||||
import { isGemma4ModelId } from "../../shared/google-models.js";
|
||||
import { sanitizeGoogleTurnOrdering } from "./bootstrap.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Sanitizes historical embedded-agent message images and empty content blocks.
|
||||
*/
|
||||
import type { ImageSanitizationLimits } from "../image-sanitization.js";
|
||||
import type { AgentMessage, AgentToolResult } from "../runtime/index.js";
|
||||
import type { ToolCallIdMode } from "../tool-call-id.js";
|
||||
@@ -28,6 +31,7 @@ function ensureNonEmptyContent<T>(content: T[]): T[] {
|
||||
return [{ type: "text", text: EMPTY_CONTENT_PLACEHOLDER }] as T[];
|
||||
}
|
||||
|
||||
/** Return true when an assistant turn contains no usable content blocks. */
|
||||
export function isEmptyAssistantMessageContent(
|
||||
message: Extract<AgentMessage, { role: "assistant" }>,
|
||||
): boolean {
|
||||
@@ -50,6 +54,7 @@ export function isEmptyAssistantMessageContent(
|
||||
});
|
||||
}
|
||||
|
||||
/** Resize/remove unsafe image payloads while keeping transcript turns valid. */
|
||||
export async function sanitizeSessionMessagesImages(
|
||||
messages: AgentMessage[],
|
||||
label: string,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Normalizes outbound message text to suppress duplicate send actions.
|
||||
*/
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
|
||||
const MIN_DUPLICATE_TEXT_LENGTH = 10;
|
||||
@@ -17,6 +20,7 @@ export function normalizeTextForComparison(text: string): string {
|
||||
.trim();
|
||||
}
|
||||
|
||||
/** Compare already-normalized message text against prior sends. */
|
||||
export function isMessagingToolDuplicateNormalized(
|
||||
normalized: string,
|
||||
normalizedSentTexts: string[],
|
||||
@@ -41,6 +45,7 @@ export function isMessagingToolDuplicateNormalized(
|
||||
});
|
||||
}
|
||||
|
||||
/** Return true when raw message text duplicates a prior sent message. */
|
||||
export function isMessagingToolDuplicate(text: string, sentTexts: string[]): boolean {
|
||||
if (sentTexts.length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Normalizes OpenAI Responses reasoning/tool-call history for safe replay.
|
||||
*/
|
||||
import { createHash } from "node:crypto";
|
||||
import type { AgentMessage } from "../runtime/index.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Converts raw provider/transport errors into concise user-facing copy.
|
||||
*/
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
@@ -31,6 +34,7 @@ import {
|
||||
isTimeoutErrorMessage,
|
||||
} from "./failover-matches.js";
|
||||
|
||||
/** Format the billing failure copy with optional provider/model context. */
|
||||
export function formatBillingErrorMessage(provider?: string, model?: string): string {
|
||||
const providerName = provider?.trim();
|
||||
const modelName = model?.trim();
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Resolves fallback thinking levels for providers that require reasoning.
|
||||
*/
|
||||
import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization";
|
||||
import { normalizeThinkLevel, type ThinkLevel } from "../../auto-reply/thinking.js";
|
||||
import { isReasoningConstraintErrorMessage } from "./errors.js";
|
||||
@@ -20,6 +23,7 @@ function extractSupportedValues(raw: string): string[] {
|
||||
);
|
||||
}
|
||||
|
||||
/** Pick a configured or provider-safe reasoning level for fallback attempts. */
|
||||
export function pickFallbackThinkingLevel(params: {
|
||||
message?: string;
|
||||
attempted: Set<ThinkLevel>;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Normalizes embedded-agent conversation turn ordering for provider contracts.
|
||||
*/
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { AgentMessage } from "../runtime/index.js";
|
||||
import { extractToolCallsFromAssistant, extractToolResultId } from "../tool-call-id.js";
|
||||
@@ -349,6 +352,7 @@ export function validateGeminiTurns(messages: AgentMessage[]): AgentMessage[] {
|
||||
});
|
||||
}
|
||||
|
||||
/** Merge adjacent user turns into a single provider-compatible user message. */
|
||||
export function mergeConsecutiveUserTurns(
|
||||
previous: Extract<AgentMessage, { role: "user" }>,
|
||||
current: Extract<AgentMessage, { role: "user" }>,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Loads bundle-provided LSP server config for embedded-agent sessions.
|
||||
*/
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { BundleLspServerConfig } from "../plugins/bundle-lsp.js";
|
||||
import { loadEnabledBundleLspConfig } from "../plugins/bundle-lsp.js";
|
||||
@@ -7,6 +10,7 @@ type EmbeddedAgentLspConfig = {
|
||||
diagnostics: Array<{ pluginId: string; message: string }>;
|
||||
};
|
||||
|
||||
/** Resolve enabled embedded-agent LSP servers and diagnostics. */
|
||||
export function loadEmbeddedAgentLspConfig(params: {
|
||||
workspaceDir: string;
|
||||
cfg?: OpenClawConfig;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Identifies messaging tools and send actions during embedded-agent runs.
|
||||
*/
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { getChannelPlugin, normalizeChannelId } from "../channels/plugins/index.js";
|
||||
|
||||
@@ -10,12 +13,14 @@ const MESSAGE_TOOL_SEND_ACTIONS = new Set([
|
||||
"upload-file",
|
||||
]);
|
||||
|
||||
/** Return true when a message action sends or uploads user-visible content. */
|
||||
export function isMessageToolSendActionName(action: unknown): boolean {
|
||||
const normalized = normalizeOptionalString(action) ?? "";
|
||||
return MESSAGE_TOOL_SEND_ACTIONS.has(normalized);
|
||||
}
|
||||
|
||||
// Provider docking: any plugin with `actions` opts into messaging tool handling.
|
||||
/** Return true for core or channel-plugin messaging tool names. */
|
||||
export function isMessagingTool(toolName: string): boolean {
|
||||
if (CORE_MESSAGING_TOOLS.has(toolName)) {
|
||||
return true;
|
||||
@@ -24,6 +29,7 @@ export function isMessagingTool(toolName: string): boolean {
|
||||
return Boolean(providerId && getChannelPlugin(providerId)?.actions);
|
||||
}
|
||||
|
||||
/** Return true when the specific tool invocation is an outbound send. */
|
||||
export function isMessagingToolSendAction(
|
||||
toolName: string,
|
||||
args: Record<string, unknown>,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* Shared messaging-tool metadata types captured from embedded-agent runs.
|
||||
*/
|
||||
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
|
||||
|
||||
// Messaging tool metadata captured during embedded agent runs.
|
||||
export type MessagingToolSend = {
|
||||
tool: string;
|
||||
provider: string;
|
||||
@@ -13,7 +15,6 @@ export type MessagingToolSend = {
|
||||
mediaUrls?: string[];
|
||||
};
|
||||
|
||||
// Reply payload subset preserved for message-tool idempotency and delivery.
|
||||
export type MessagingToolSourceReplyPayload = Pick<
|
||||
ReplyPayload,
|
||||
| "audioAsVoice"
|
||||
|
||||
Reference in New Issue
Block a user