mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe agent trimmed readers
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import {
|
||||
lowercasePreservingWhitespace,
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
readStringValue,
|
||||
resolvePrimaryStringValue,
|
||||
} from "../shared/string-coerce.js";
|
||||
@@ -216,7 +217,7 @@ export function resolveFallbackAgentId(params: {
|
||||
agentId?: string | null;
|
||||
sessionKey?: string | null;
|
||||
}): string {
|
||||
const explicitAgentId = typeof params.agentId === "string" ? params.agentId.trim() : "";
|
||||
const explicitAgentId = normalizeOptionalString(params.agentId) ?? "";
|
||||
if (explicitAgentId) {
|
||||
return normalizeAgentId(explicitAgentId);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type { EmbeddedContextFile } from "./pi-embedded-helpers.js";
|
||||
import type { WorkspaceBootstrapFile } from "./workspace.js";
|
||||
|
||||
@@ -74,7 +75,7 @@ function normalizeSeenSignatures(signatures?: string[]): string[] {
|
||||
const seen = new Set<string>();
|
||||
const result: string[] = [];
|
||||
for (const signature of signatures) {
|
||||
const value = typeof signature === "string" ? signature.trim() : "";
|
||||
const value = normalizeOptionalString(signature) ?? "";
|
||||
if (!value || seen.has(value)) {
|
||||
continue;
|
||||
}
|
||||
@@ -116,7 +117,7 @@ export function resolveBootstrapWarningSignaturesSeen(report?: {
|
||||
}
|
||||
const single =
|
||||
typeof truncation?.promptWarningSignature === "string"
|
||||
? truncation.promptWarningSignature.trim()
|
||||
? (normalizeOptionalString(truncation.promptWarningSignature) ?? "")
|
||||
: "";
|
||||
return single ? [single] : [];
|
||||
}
|
||||
@@ -128,7 +129,7 @@ export function buildBootstrapInjectionStats(params: {
|
||||
const injectedByPath = new Map<string, string>();
|
||||
const injectedByBaseName = new Map<string, string>();
|
||||
for (const file of params.injectedFiles) {
|
||||
const pathValue = typeof file.path === "string" ? file.path.trim() : "";
|
||||
const pathValue = normalizeOptionalString(file.path) ?? "";
|
||||
if (!pathValue) {
|
||||
continue;
|
||||
}
|
||||
@@ -142,7 +143,7 @@ export function buildBootstrapInjectionStats(params: {
|
||||
}
|
||||
}
|
||||
return params.bootstrapFiles.map((file) => {
|
||||
const pathValue = typeof file.path === "string" ? file.path.trim() : "";
|
||||
const pathValue = normalizeOptionalString(file.path) ?? "";
|
||||
const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
|
||||
const injected =
|
||||
(pathValue ? injectedByPath.get(pathValue) : undefined) ??
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export function buildModelAliasLines(cfg?: OpenClawConfig) {
|
||||
const models = cfg?.agents?.defaults?.models ?? {};
|
||||
const entries: Array<{ alias: string; model: string }> = [];
|
||||
for (const [keyRaw, entryRaw] of Object.entries(models)) {
|
||||
const model = String(keyRaw ?? "").trim();
|
||||
const model = normalizeOptionalString(String(keyRaw ?? "")) ?? "";
|
||||
if (!model) {
|
||||
continue;
|
||||
}
|
||||
const alias = String((entryRaw as { alias?: string } | undefined)?.alias ?? "").trim();
|
||||
const alias =
|
||||
normalizeOptionalString(String((entryRaw as { alias?: string } | undefined)?.alias ?? "")) ??
|
||||
"";
|
||||
if (!alias) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { type OpenClawConfig, loadConfig } from "../config/config.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { augmentModelCatalogWithProviderPlugins } from "../plugins/provider-runtime.runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveOpenClawAgentDir } from "./agent-paths.js";
|
||||
import { ensureOpenClawModelsJson } from "./models-config.js";
|
||||
import { normalizeProviderId } from "./provider-id.js";
|
||||
@@ -132,18 +135,18 @@ export async function loadModelCatalog(params?: {
|
||||
const entries = Array.isArray(registry) ? registry : registry.getAll();
|
||||
logStage("registry-read", `entries=${entries.length}`);
|
||||
for (const entry of entries) {
|
||||
const id = String(entry?.id ?? "").trim();
|
||||
const id = normalizeOptionalString(String(entry?.id ?? "")) ?? "";
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
const provider = String(entry?.provider ?? "").trim();
|
||||
const provider = normalizeOptionalString(String(entry?.provider ?? "")) ?? "";
|
||||
if (!provider) {
|
||||
continue;
|
||||
}
|
||||
if (shouldSuppressBuiltInModel({ provider, id })) {
|
||||
continue;
|
||||
}
|
||||
const name = String(entry?.name ?? id).trim() || id;
|
||||
const name = normalizeOptionalString(String(entry?.name ?? id)) || id;
|
||||
const contextWindow =
|
||||
typeof entry?.contextWindow === "number" && entry.contextWindow > 0
|
||||
? entry.contextWindow
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "../config/model-input.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { sanitizeForLog } from "../terminal/ansi.js";
|
||||
import { resolveAuthProfileOrder } from "./auth-profiles/order.js";
|
||||
import { ensureAuthProfileStore, loadAuthProfileStoreForRuntime } from "./auth-profiles/store.js";
|
||||
@@ -386,8 +387,8 @@ function resolveFallbackCandidates(params: {
|
||||
: null;
|
||||
const defaultProvider = primary?.provider ?? DEFAULT_PROVIDER;
|
||||
const defaultModel = primary?.model ?? DEFAULT_MODEL;
|
||||
const providerRaw = String(params.provider ?? "").trim() || defaultProvider;
|
||||
const modelRaw = String(params.model ?? "").trim() || defaultModel;
|
||||
const providerRaw = normalizeOptionalString(String(params.provider ?? "")) || defaultProvider;
|
||||
const modelRaw = normalizeOptionalString(String(params.model ?? "")) || defaultModel;
|
||||
const normalizedPrimary = normalizeModelRef(providerRaw, modelRaw);
|
||||
const configuredPrimary = normalizeModelRef(defaultProvider, defaultModel);
|
||||
const aliasIndex = buildModelAliasIndex({
|
||||
@@ -455,7 +456,7 @@ const PROBE_STATE_TTL_MS = 24 * 60 * 60 * 1000;
|
||||
const MAX_PROBE_KEYS = 256;
|
||||
|
||||
function resolveProbeThrottleKey(provider: string, agentDir?: string): string {
|
||||
const scope = String(agentDir ?? "").trim();
|
||||
const scope = normalizeOptionalString(String(agentDir ?? "")) ?? "";
|
||||
return scope ? `${scope}${PROBE_SCOPE_DELIMITER}${provider}` : provider;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { inferParamBFromIdOrName } from "../shared/model-param-b.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { normalizeProviderId } from "./provider-id.js";
|
||||
|
||||
const OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
|
||||
@@ -193,7 +196,7 @@ async function fetchOpenRouterModels(fetchImpl: typeof fetch): Promise<OpenRoute
|
||||
return null;
|
||||
}
|
||||
const obj = entry as Record<string, unknown>;
|
||||
const id = typeof obj.id === "string" ? obj.id.trim() : "";
|
||||
const id = normalizeOptionalString(obj.id) ?? "";
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { resolvePluginSetupCliBackendRuntime } from "../plugins/setup-registry.r
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { sanitizeForLog, stripAnsi } from "../terminal/ansi.js";
|
||||
import {
|
||||
@@ -276,7 +277,9 @@ export function buildModelAliasIndex(params: {
|
||||
if (!parsed) {
|
||||
continue;
|
||||
}
|
||||
const alias = String((entryRaw as { alias?: string } | undefined)?.alias ?? "").trim();
|
||||
const alias =
|
||||
normalizeOptionalString(String((entryRaw as { alias?: string } | undefined)?.alias ?? "")) ??
|
||||
"";
|
||||
if (!alias) {
|
||||
continue;
|
||||
}
|
||||
@@ -603,11 +606,11 @@ export function buildConfiguredModelCatalog(params: { cfg: OpenClawConfig }): Mo
|
||||
continue;
|
||||
}
|
||||
for (const model of provider.models) {
|
||||
const id = typeof model?.id === "string" ? model.id.trim() : "";
|
||||
const id = normalizeOptionalString(model?.id) ?? "";
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
const name = typeof model?.name === "string" && model.name.trim() ? model.name.trim() : id;
|
||||
const name = normalizeOptionalString(model?.name) || id;
|
||||
const contextWindow =
|
||||
typeof model?.contextWindow === "number" && model.contextWindow > 0
|
||||
? model.contextWindow
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
normalizeAssistantPhase,
|
||||
parseAssistantTextSignature,
|
||||
} from "../shared/chat-message-content.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOpenAIStrictToolParameters,
|
||||
resolveOpenAIStrictToolFlagForInventory,
|
||||
@@ -39,7 +40,7 @@ function toNonEmptyString(value: unknown): string | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
const trimmed = normalizeOptionalString(value) ?? "";
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
@@ -223,7 +224,7 @@ function extractReasoningSummaryText(value: unknown): string {
|
||||
return "";
|
||||
}
|
||||
const record = item as { text?: unknown };
|
||||
return typeof record.text === "string" ? record.text.trim() : "";
|
||||
return normalizeOptionalString(record.text) ?? "";
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join("\n")
|
||||
@@ -239,7 +240,7 @@ function extractResponseReasoningText(item: unknown): string {
|
||||
if (summaryText) {
|
||||
return summaryText;
|
||||
}
|
||||
return typeof record.content === "string" ? record.content.trim() : "";
|
||||
return normalizeOptionalString(record.content) ?? "";
|
||||
}
|
||||
|
||||
export function convertTools(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type { AuthProfileCredential, AuthProfileStore } from "./auth-profiles.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
@@ -14,7 +15,7 @@ export type PiCredentialMap = Record<string, PiCredential>;
|
||||
|
||||
export function convertAuthProfileCredentialToPi(cred: AuthProfileCredential): PiCredential | null {
|
||||
if (cred.type === "api_key") {
|
||||
const key = typeof cred.key === "string" ? cred.key.trim() : "";
|
||||
const key = normalizeOptionalString(cred.key) ?? "";
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
@@ -22,7 +23,7 @@ export function convertAuthProfileCredentialToPi(cred: AuthProfileCredential): P
|
||||
}
|
||||
|
||||
if (cred.type === "token") {
|
||||
const token = typeof cred.token === "string" ? cred.token.trim() : "";
|
||||
const token = normalizeOptionalString(cred.token) ?? "";
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
@@ -37,8 +38,8 @@ export function convertAuthProfileCredentialToPi(cred: AuthProfileCredential): P
|
||||
}
|
||||
|
||||
if (cred.type === "oauth") {
|
||||
const access = typeof cred.access === "string" ? cred.access.trim() : "";
|
||||
const refresh = typeof cred.refresh === "string" ? cred.refresh.trim() : "";
|
||||
const access = normalizeOptionalString(cred.access) ?? "";
|
||||
const refresh = normalizeOptionalString(cred.refresh) ?? "";
|
||||
if (!access || !refresh || !Number.isFinite(cred.expires) || cred.expires <= 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -56,7 +57,7 @@ export function convertAuthProfileCredentialToPi(cred: AuthProfileCredential): P
|
||||
export function resolvePiCredentialMapFromStore(store: AuthProfileStore): PiCredentialMap {
|
||||
const credentials: PiCredentialMap = {};
|
||||
for (const credential of Object.values(store.profiles)) {
|
||||
const provider = normalizeProviderId(String(credential.provider ?? "")).trim();
|
||||
const provider = normalizeProviderId(String(credential.provider ?? ""));
|
||||
if (!provider || credentials[provider]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getChannelPlugin, normalizeChannelId } from "../channels/plugins/index.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export type MessagingToolSend = {
|
||||
tool: string;
|
||||
@@ -23,7 +24,7 @@ export function isMessagingToolSendAction(
|
||||
toolName: string,
|
||||
args: Record<string, unknown>,
|
||||
): boolean {
|
||||
const action = typeof args.action === "string" ? args.action.trim() : "";
|
||||
const action = normalizeOptionalString(args.action) ?? "";
|
||||
if (toolName === "sessions_send") {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
import { emitAgentEvent } from "../infra/agent-events.js";
|
||||
import { createInlineCodeState } from "../markdown/code-spans.js";
|
||||
import { resolveAssistantMessagePhase } from "../shared/chat-message-content.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
isMessagingToolDuplicateNormalized,
|
||||
normalizeTextForComparison,
|
||||
@@ -75,8 +76,8 @@ function isTranscriptOnlyOpenClawAssistantMessage(message: AgentMessage | undefi
|
||||
if (!message || message.role !== "assistant") {
|
||||
return false;
|
||||
}
|
||||
const provider = typeof message.provider === "string" ? message.provider.trim() : "";
|
||||
const model = typeof message.model === "string" ? message.model.trim() : "";
|
||||
const provider = normalizeOptionalString(message.provider) ?? "";
|
||||
const model = normalizeOptionalString(message.model) ?? "";
|
||||
return provider === "openclaw" && (model === "delivery-mirror" || model === "gateway-injected");
|
||||
}
|
||||
|
||||
|
||||
@@ -342,8 +342,8 @@ function readExecApprovalPendingDetails(result: unknown): {
|
||||
if (details.status !== "approval-pending") {
|
||||
return null;
|
||||
}
|
||||
const approvalId = typeof details.approvalId === "string" ? details.approvalId.trim() : "";
|
||||
const approvalSlug = typeof details.approvalSlug === "string" ? details.approvalSlug.trim() : "";
|
||||
const approvalId = readStringValue(details.approvalId) ?? "";
|
||||
const approvalSlug = readStringValue(details.approvalSlug) ?? "";
|
||||
const command = typeof details.command === "string" ? details.command : "";
|
||||
const host = details.host === "node" ? "node" : details.host === "gateway" ? "gateway" : null;
|
||||
if (!approvalId || !approvalSlug || !command || !host) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { listTasksForOwnerKey } from "../tasks/runtime-internal.js";
|
||||
import type { TaskRecord, TaskRuntime, TaskStatus } from "../tasks/task-registry.types.js";
|
||||
|
||||
@@ -10,13 +11,13 @@ export function findActiveSessionTask(params: {
|
||||
statuses?: ReadonlySet<TaskStatus>;
|
||||
sourceIdPrefix?: string;
|
||||
}): TaskRecord | undefined {
|
||||
const normalizedSessionKey = params.sessionKey?.trim();
|
||||
const normalizedSessionKey = normalizeOptionalString(params.sessionKey);
|
||||
if (!normalizedSessionKey) {
|
||||
return undefined;
|
||||
}
|
||||
const statuses = params.statuses ?? DEFAULT_ACTIVE_STATUSES;
|
||||
const taskKind = params.taskKind?.trim();
|
||||
const sourceIdPrefix = params.sourceIdPrefix?.trim();
|
||||
const taskKind = normalizeOptionalString(params.taskKind);
|
||||
const sourceIdPrefix = normalizeOptionalString(params.sourceIdPrefix);
|
||||
const matches = listTasksForOwnerKey(normalizedSessionKey).filter((task) => {
|
||||
if (task.scopeKind !== "session") {
|
||||
return false;
|
||||
@@ -31,7 +32,7 @@ export function findActiveSessionTask(params: {
|
||||
return false;
|
||||
}
|
||||
if (sourceIdPrefix) {
|
||||
const sourceId = task.sourceId?.trim() ?? "";
|
||||
const sourceId = normalizeOptionalString(task.sourceId) ?? "";
|
||||
if (sourceId !== sourceIdPrefix && !sourceId.startsWith(`${sourceIdPrefix}:`)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import type { Skill } from "./skill-contract.js";
|
||||
|
||||
type SkillSourceCompat = Skill & {
|
||||
@@ -8,11 +9,10 @@ type SkillSourceCompat = Skill & {
|
||||
|
||||
export function resolveSkillSource(skill: Skill): string {
|
||||
const compatSkill = skill as SkillSourceCompat;
|
||||
const canonical = typeof compatSkill.source === "string" ? compatSkill.source.trim() : "";
|
||||
const canonical = normalizeOptionalString(compatSkill.source) ?? "";
|
||||
if (canonical) {
|
||||
return canonical;
|
||||
}
|
||||
const legacy =
|
||||
typeof compatSkill.sourceInfo?.source === "string" ? compatSkill.sourceInfo.source.trim() : "";
|
||||
const legacy = normalizeOptionalString(compatSkill.sourceInfo?.source) ?? "";
|
||||
return legacy || "unknown";
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
function normalizeSummaryWhitespace(value: string): string {
|
||||
return value.replace(/\s+/g, " ").trim();
|
||||
}
|
||||
@@ -41,12 +43,12 @@ export function summarizeToolDescriptionText(params: {
|
||||
displaySummary?: string | null;
|
||||
maxLen?: number;
|
||||
}): string {
|
||||
const explicit = typeof params.displaySummary === "string" ? params.displaySummary.trim() : "";
|
||||
const explicit = normalizeOptionalString(params.displaySummary) ?? "";
|
||||
if (explicit) {
|
||||
return truncateSummary(normalizeSummaryWhitespace(explicit), params.maxLen);
|
||||
}
|
||||
|
||||
const raw = typeof params.rawDescription === "string" ? params.rawDescription.trim() : "";
|
||||
const raw = normalizeOptionalString(params.rawDescription) ?? "";
|
||||
if (!raw) {
|
||||
return "Tool";
|
||||
}
|
||||
@@ -92,7 +94,7 @@ export function describeToolForVerbose(params: {
|
||||
fallback: string;
|
||||
maxLen?: number;
|
||||
}): string {
|
||||
const raw = typeof params.rawDescription === "string" ? params.rawDescription.trim() : "";
|
||||
const raw = normalizeOptionalString(params.rawDescription) ?? "";
|
||||
if (!raw) {
|
||||
return params.fallback;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export function coerceDisplayValue(
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
const firstLine = trimmed.split(/\r?\n/)[0]?.trim() ?? "";
|
||||
const firstLine = normalizeOptionalString(trimmed.split(/\r?\n/)[0]) ?? "";
|
||||
if (!firstLine) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -231,8 +231,7 @@ export function resolveWriteDetail(toolKey: string, args: unknown): string | und
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const path =
|
||||
resolvePathArg(record) ?? (typeof record.url === "string" ? record.url.trim() : undefined);
|
||||
const path = resolvePathArg(record) ?? normalizeOptionalString(record.url);
|
||||
if (!path) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -264,7 +263,7 @@ export function resolveWebSearchDetail(args: unknown): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const query = typeof record.query === "string" ? record.query.trim() : undefined;
|
||||
const query = normalizeOptionalString(record.query);
|
||||
const count =
|
||||
typeof record.count === "number" && Number.isFinite(record.count) && record.count > 0
|
||||
? Math.floor(record.count)
|
||||
@@ -283,12 +282,12 @@ export function resolveWebFetchDetail(args: unknown): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const url = typeof record.url === "string" ? record.url.trim() : undefined;
|
||||
const url = normalizeOptionalString(record.url);
|
||||
if (!url) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const mode = typeof record.extractMode === "string" ? record.extractMode.trim() : undefined;
|
||||
const mode = normalizeOptionalString(record.extractMode);
|
||||
const maxChars =
|
||||
typeof record.maxChars === "number" && Number.isFinite(record.maxChars) && record.maxChars > 0
|
||||
? Math.floor(record.maxChars)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { getPluginToolMeta } from "../plugins/tools.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveAgentDir, resolveAgentWorkspaceDir, resolveSessionAgentId } from "./agent-scope.js";
|
||||
import { getChannelAgentToolMeta } from "./channel-tools.js";
|
||||
import { resolveModel } from "./pi-embedded-runner/model.js";
|
||||
@@ -63,7 +66,7 @@ export type ResolveEffectiveToolInventoryParams = {
|
||||
};
|
||||
|
||||
function resolveEffectiveToolLabel(tool: AnyAgentTool): string {
|
||||
const rawLabel = typeof tool.label === "string" ? tool.label.trim() : "";
|
||||
const rawLabel = normalizeOptionalString(tool.label) ?? "";
|
||||
if (
|
||||
rawLabel &&
|
||||
normalizeLowercaseStringOrEmpty(rawLabel) !== normalizeLowercaseStringOrEmpty(tool.name)
|
||||
@@ -74,7 +77,7 @@ function resolveEffectiveToolLabel(tool: AnyAgentTool): string {
|
||||
}
|
||||
|
||||
function resolveRawToolDescription(tool: AnyAgentTool): string {
|
||||
return typeof tool.description === "string" ? tool.description.trim() : "";
|
||||
return normalizeOptionalString(tool.description) ?? "";
|
||||
}
|
||||
|
||||
function summarizeToolDescription(tool: AnyAgentTool): string {
|
||||
|
||||
@@ -66,10 +66,7 @@ export async function listSpawnedSessionKeys(params: {
|
||||
},
|
||||
});
|
||||
const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
|
||||
const keys = sessions
|
||||
.map((entry) => (typeof entry?.key === "string" ? entry.key : ""))
|
||||
.map((value) => value.trim())
|
||||
.filter(Boolean);
|
||||
const keys = sessions.map((entry) => normalizeOptionalString(entry?.key) ?? "").filter(Boolean);
|
||||
return new Set(keys);
|
||||
} catch {
|
||||
return new Set();
|
||||
@@ -238,7 +235,7 @@ async function callGatewayResolveSessionId(params: {
|
||||
method: "sessions.resolve",
|
||||
params: buildSessionIdResolveParams(params),
|
||||
});
|
||||
const key = typeof result?.key === "string" ? result.key.trim() : "";
|
||||
const key = normalizeOptionalString(result?.key) ?? "";
|
||||
if (!key) {
|
||||
throw new Error(
|
||||
`Session not found: ${params.sessionId} (use the full sessionKey from sessions_list)`,
|
||||
@@ -298,7 +295,7 @@ async function resolveSessionKeyFromKey(params: {
|
||||
spawnedBy: params.restrictToSpawned ? params.requesterInternalKey : undefined,
|
||||
},
|
||||
});
|
||||
const key = typeof result?.key === "string" ? result.key.trim() : "";
|
||||
const key = normalizeOptionalString(result?.key) ?? "";
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user