mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
refactor: remove residual normalization aliases (#122956)
* refactor: remove residual normalization aliases * test(gateway): isolate approval authority handshake
This commit is contained in:
committed by
GitHub
parent
061c9c2f7f
commit
ffb2ed9e89
@@ -1,3 +1,5 @@
|
||||
import { parseStrictNonNegativeInteger } from "@openclaw/normalization-core/number-coercion";
|
||||
|
||||
export interface PromptTemplate {
|
||||
name: string;
|
||||
description?: string;
|
||||
@@ -39,11 +41,6 @@ export function parseCommandArgs(argsString: string): string[] {
|
||||
return args;
|
||||
}
|
||||
|
||||
function parseSafeNonNegativeInteger(raw: string): number | undefined {
|
||||
const parsed = Number(raw);
|
||||
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitute prompt template placeholders (`$1`, `$@`, `$ARGUMENTS`, `${@:N}`, `${@:N:L}`) with command arguments.
|
||||
*
|
||||
@@ -53,7 +50,7 @@ function parseSafeNonNegativeInteger(raw: string): number | undefined {
|
||||
export function substituteArgs(content: string, args: string[]): string {
|
||||
let result = content;
|
||||
result = result.replace(/\$(\d+)/g, (_, num: string) => {
|
||||
const parsed = parseSafeNonNegativeInteger(num);
|
||||
const parsed = parseStrictNonNegativeInteger(num);
|
||||
if (parsed === undefined || parsed <= 0) {
|
||||
return "";
|
||||
}
|
||||
@@ -62,7 +59,7 @@ export function substituteArgs(content: string, args: string[]): string {
|
||||
result = result.replace(
|
||||
/\$\{@:(\d+)(?::(\d+))?\}/g,
|
||||
(_, startStr: string, lengthStr?: string) => {
|
||||
const parsedStart = parseSafeNonNegativeInteger(startStr);
|
||||
const parsedStart = parseStrictNonNegativeInteger(startStr);
|
||||
if (parsedStart === undefined) {
|
||||
return "";
|
||||
}
|
||||
@@ -73,7 +70,7 @@ export function substituteArgs(content: string, args: string[]): string {
|
||||
start = 0;
|
||||
}
|
||||
if (lengthStr) {
|
||||
const length = parseSafeNonNegativeInteger(lengthStr);
|
||||
const length = parseStrictNonNegativeInteger(lengthStr);
|
||||
if (length === undefined) {
|
||||
return "";
|
||||
}
|
||||
|
||||
+1
-5
@@ -78,10 +78,6 @@ export function isHelpOrVersionInvocation(argv: string[]): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
function parsePositiveInt(value: string): number | undefined {
|
||||
return parseStrictPositiveInteger(value);
|
||||
}
|
||||
|
||||
export function hasFlag(argv: string[], name: string): boolean {
|
||||
const args = argv.slice(2);
|
||||
for (const arg of args) {
|
||||
@@ -497,7 +493,7 @@ export function getPositiveIntFlagValue(argv: string[], name: string): number |
|
||||
}
|
||||
// Keep absent distinct from present-but-invalid so route-first callers can
|
||||
// defer invalid input to Commander instead of silently applying defaults.
|
||||
return parsePositiveInt(raw) ?? null;
|
||||
return parseStrictPositiveInteger(raw) ?? null;
|
||||
}
|
||||
|
||||
export function getCommandPathWithRootOptions(argv: string[], depth = 2): string[] {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
// Program helper tests cover shared command registration and help helpers.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
collectOption,
|
||||
parsePositiveIntOrUndefined,
|
||||
parseStrictPositiveIntOption,
|
||||
} from "./helpers.js";
|
||||
import { collectOption, parseStrictPositiveIntOption } from "./helpers.js";
|
||||
|
||||
describe("program helpers", () => {
|
||||
it("collectOption appends values in order", () => {
|
||||
@@ -12,25 +8,6 @@ describe("program helpers", () => {
|
||||
expect(collectOption("b", ["a"])).toEqual(["a", "b"]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ value: undefined, expected: undefined },
|
||||
{ value: null, expected: undefined },
|
||||
{ value: "", expected: undefined },
|
||||
{ value: 5, expected: 5 },
|
||||
{ value: 5.9, expected: undefined },
|
||||
{ value: 0, expected: undefined },
|
||||
{ value: -1, expected: undefined },
|
||||
{ value: Number.NaN, expected: undefined },
|
||||
{ value: "10", expected: 10 },
|
||||
{ value: "10ms", expected: undefined },
|
||||
{ value: "1.5", expected: undefined },
|
||||
{ value: "0", expected: undefined },
|
||||
{ value: "nope", expected: undefined },
|
||||
{ value: true, expected: undefined },
|
||||
])("parsePositiveIntOrUndefined(%j)", ({ value, expected }) => {
|
||||
expect(parsePositiveIntOrUndefined(value)).toBe(expected);
|
||||
});
|
||||
|
||||
it("parseStrictPositiveIntOption rejects partial numeric strings", () => {
|
||||
expect(parseStrictPositiveIntOption("10", "--limit")).toBe(10);
|
||||
expect(() => parseStrictPositiveIntOption("10ms", "--limit")).toThrow(
|
||||
|
||||
@@ -7,14 +7,6 @@ export function collectOption(value: string, previous: string[] = []): string[]
|
||||
return [...previous, value];
|
||||
}
|
||||
|
||||
/** Parse an optional positive integer, treating empty values as unset. */
|
||||
export function parsePositiveIntOrUndefined(value: unknown): number | undefined {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return undefined;
|
||||
}
|
||||
return parseStrictPositiveInteger(value);
|
||||
}
|
||||
|
||||
/** Commander argument parser for required positive integer options. */
|
||||
export function parseStrictPositiveIntOption(value: string, flag: string): number {
|
||||
const parsed = parseStrictPositiveInteger(value);
|
||||
|
||||
@@ -7,7 +7,6 @@ import { setVerbose } from "../../globals.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { runCommandWithRuntime } from "../cli-utils.js";
|
||||
import { formatHelpExamples } from "../help-format.js";
|
||||
import { parsePositiveIntOrUndefined } from "./helpers.js";
|
||||
|
||||
function resolveVerbose(opts: { verbose?: boolean; debug?: boolean }): boolean {
|
||||
return Boolean(opts.verbose || opts.debug);
|
||||
@@ -209,7 +208,7 @@ function registerSessionsLifecycleCommand(
|
||||
}
|
||||
|
||||
function parseTimeoutMs(timeout: unknown): number | null | undefined {
|
||||
const parsed = parsePositiveIntOrUndefined(timeout);
|
||||
const parsed = parseStrictPositiveInteger(timeout);
|
||||
if (timeout !== undefined && parsed === undefined) {
|
||||
defaultRuntime.error("--timeout must be a positive integer (milliseconds)");
|
||||
defaultRuntime.exit(1);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/** CLI entrypoint for channel message actions. */
|
||||
import { parseStrictPositiveInteger } from "@openclaw/normalization-core/number-coercion";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
@@ -15,7 +16,6 @@ import { formatCliCommand } from "../cli/command-format.js";
|
||||
import { getScopedChannelsCommandSecretTargets } from "../cli/command-secret-targets.js";
|
||||
import { resolveMessageSecretScope } from "../cli/message-secret-scope.js";
|
||||
import { createOutboundSendDeps, type CliDeps } from "../cli/outbound-send-deps.js";
|
||||
import { parsePositiveIntOrUndefined } from "../cli/program/helpers.js";
|
||||
import { withProgress } from "../cli/progress.js";
|
||||
import { getRuntimeConfig } from "../config/config.js";
|
||||
import type { OutboundSendDeps } from "../infra/outbound/deliver.js";
|
||||
@@ -159,7 +159,7 @@ export async function messageCommand(
|
||||
}
|
||||
|
||||
const { formatMessageCliText } = await import("./message-format.js");
|
||||
const displayLimit = parsePositiveIntOrUndefined(opts.limit);
|
||||
const displayLimit = parseStrictPositiveInteger(opts.limit);
|
||||
for (const line of formatMessageCliText(result, { displayLimit })) {
|
||||
runtime.log(line);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ import { createChatRunState } from "../server-chat-state.js";
|
||||
import { createExecApprovalHandlers } from "./exec-approval.js";
|
||||
import type { GatewayRequestHandlerOptions } from "./types.js";
|
||||
|
||||
vi.mock("../../infra/command-analysis/explain.js", () => ({
|
||||
resolveCommandAnalysisSummaryForDisplay: vi.fn(async () => null),
|
||||
}));
|
||||
|
||||
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
||||
|
||||
function databaseOptions(): OpenClawStateDatabaseOptions {
|
||||
|
||||
@@ -74,10 +74,6 @@ function normalizePlugin(value: unknown): OpenClawProviderIndexPlugin | undefine
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeCategories(value: unknown): readonly string[] {
|
||||
return normalizeUniqueTrimmedStringList(value);
|
||||
}
|
||||
|
||||
function normalizePreviewCatalog(params: {
|
||||
providerId: string;
|
||||
value: unknown;
|
||||
@@ -192,7 +188,7 @@ function normalizeProvider(
|
||||
return undefined;
|
||||
}
|
||||
const docs = normalizeOptionalString(value.docs) ?? "";
|
||||
const categories = normalizeCategories(value.categories);
|
||||
const categories = normalizeUniqueTrimmedStringList(value.categories);
|
||||
const authChoices = normalizeAuthChoices({
|
||||
providerId,
|
||||
providerName: name,
|
||||
|
||||
@@ -228,10 +228,6 @@ function assertWritableInstalledPluginIndexStoreOptions(
|
||||
}
|
||||
}
|
||||
|
||||
function parseJsonColumn(value: string): unknown {
|
||||
return safeParseJson(value);
|
||||
}
|
||||
|
||||
function parseInstalledPluginIndexSqliteRow(
|
||||
row: InstalledPluginIndexSqliteRow | undefined,
|
||||
): InstalledPluginIndex | null {
|
||||
@@ -247,9 +243,9 @@ function parseInstalledPluginIndexSqliteRow(
|
||||
policyHash: row.policy_hash,
|
||||
generatedAtMs: Number(row.generated_at_ms),
|
||||
...(row.refresh_reason ? { refreshReason: row.refresh_reason } : {}),
|
||||
installRecords: parseJsonColumn(row.install_records_json),
|
||||
plugins: parseJsonColumn(row.plugins_json),
|
||||
diagnostics: parseJsonColumn(row.diagnostics_json),
|
||||
installRecords: safeParseJson(row.install_records_json),
|
||||
plugins: safeParseJson(row.plugins_json),
|
||||
diagnostics: safeParseJson(row.diagnostics_json),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Persisted settings normalizers shared by the settings storage owner.
|
||||
|
||||
/** Unknown shapes fall back to []; stale and duplicate ids are dropped. */
|
||||
export function normalizePinnedAgentIds(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
const pinned: string[] = [];
|
||||
for (const entry of value) {
|
||||
if (typeof entry !== "string") {
|
||||
continue;
|
||||
}
|
||||
const agentId = entry.trim();
|
||||
if (agentId && !pinned.includes(agentId)) {
|
||||
pinned.push(agentId);
|
||||
}
|
||||
}
|
||||
return pinned;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { gatewayOriginScope } from "@openclaw/gateway-client/browser";
|
||||
import { safeParseJson } from "@openclaw/normalization-core";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { normalizeUniqueTrimmedStringList } from "@openclaw/normalization-core/string-normalization";
|
||||
import {
|
||||
DEFAULT_SIDEBAR_ENTRIES,
|
||||
normalizeSidebarEntries,
|
||||
@@ -19,7 +20,6 @@ import {
|
||||
import { normalizeChatSplitLayout, type ChatSplitLayout } from "../pages/chat/split-layout.ts";
|
||||
import { resolveControlUiBasePath } from "./browser.ts";
|
||||
import { parseImportedCustomTheme, type ImportedCustomTheme } from "./custom-theme.ts";
|
||||
import { normalizePinnedAgentIds } from "./settings-normalizers.ts";
|
||||
import { parseThemeSelection, type ThemeMode, type ThemeName } from "./theme.ts";
|
||||
import { normalizeLocalUserIdentity, type LocalUserIdentity } from "./user-identity.ts";
|
||||
|
||||
@@ -546,7 +546,7 @@ export function loadSettings(): UiSettings {
|
||||
typeof parsed.showAdvancedSettings === "boolean"
|
||||
? parsed.showAdvancedSettings
|
||||
: defaults.showAdvancedSettings,
|
||||
pinnedAgentIds: normalizePinnedAgentIds(parsed.pinnedAgentIds),
|
||||
pinnedAgentIds: normalizeUniqueTrimmedStringList(parsed.pinnedAgentIds),
|
||||
textScale:
|
||||
typeof parsed.textScale === "number" &&
|
||||
normalizeTextScale(parsed.textScale) !== UI_APPEARANCE_DEFAULTS.textScale
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { sortUniqueStrings } from "@openclaw/normalization-core/string-normalization";
|
||||
import { normalizeSortedUniqueTrimmedStringList } from "@openclaw/normalization-core/string-normalization";
|
||||
import type { AgentsListResult } from "../../api/types.ts";
|
||||
import type { ApplicationContext } from "../../app/context.ts";
|
||||
import { listSelectableAgents } from "../../lib/agents/display.ts";
|
||||
@@ -12,10 +12,6 @@ import { resolveCronTimezoneSuggestions } from "./timezone-suggestions.ts";
|
||||
|
||||
export const THINKING_SUGGESTIONS = ["off", "minimal", "low", "medium", "high"];
|
||||
|
||||
function unique(values: string[]): string[] {
|
||||
return sortUniqueStrings(values.map((value) => value.trim()).filter(Boolean));
|
||||
}
|
||||
|
||||
export function buildCronSuggestions(params: {
|
||||
channels: ApplicationContext["channels"]["state"];
|
||||
runtimeConfig: ApplicationContext["runtimeConfig"]["state"];
|
||||
@@ -30,7 +26,7 @@ export function buildCronSuggestions(params: {
|
||||
.filter((entry) => entry.kind === "system")
|
||||
.map((entry) => entry.id.trim()),
|
||||
);
|
||||
const agentSuggestions = unique([
|
||||
const agentSuggestions = normalizeSortedUniqueTrimmedStringList([
|
||||
...listSelectableAgents(params.agentsList?.agents ?? []).map((entry) => entry.id.trim()),
|
||||
...params.cron.cronJobs.map((job) =>
|
||||
typeof job.agentId === "string" && !systemAgentIds.has(job.agentId.trim())
|
||||
@@ -38,7 +34,7 @@ export function buildCronSuggestions(params: {
|
||||
: "",
|
||||
),
|
||||
]);
|
||||
const modelSuggestions = unique([
|
||||
const modelSuggestions = normalizeSortedUniqueTrimmedStringList([
|
||||
...params.modelSuggestions,
|
||||
...resolveConfiguredCronModelSuggestions(configValue),
|
||||
...params.cron.cronJobs.map((job) => {
|
||||
@@ -60,7 +56,10 @@ export function buildCronSuggestions(params: {
|
||||
.filter((value): value is string => typeof value === "string")
|
||||
.map((value) => value.trim())
|
||||
.filter(Boolean);
|
||||
const deliveryTargets = unique([...jobTargets, ...accountTargets]);
|
||||
const deliveryTargets = normalizeSortedUniqueTrimmedStringList([
|
||||
...jobTargets,
|
||||
...accountTargets,
|
||||
]);
|
||||
return {
|
||||
agentSuggestions,
|
||||
modelSuggestions,
|
||||
|
||||
Reference in New Issue
Block a user