mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 10:40:23 +00:00
refactor(core): extract shared dedup helpers
This commit is contained in:
@@ -540,12 +540,9 @@ async function resolveOutsideBoundaryPathAsync(params: {
|
||||
return null;
|
||||
}
|
||||
const kind = await getPathKind(params.context.absolutePath, false);
|
||||
return buildOutsideLexicalBoundaryPath({
|
||||
return buildOutsideBoundaryPathFromContext({
|
||||
boundaryLabel: params.boundaryLabel,
|
||||
rootCanonicalPath: params.context.rootCanonicalPath,
|
||||
absolutePath: params.context.absolutePath,
|
||||
canonicalOutsideLexicalPath: params.context.canonicalOutsideLexicalPath,
|
||||
rootPath: params.context.rootPath,
|
||||
context: params.context,
|
||||
kind,
|
||||
});
|
||||
}
|
||||
@@ -558,13 +555,25 @@ function resolveOutsideBoundaryPathSync(params: {
|
||||
return null;
|
||||
}
|
||||
const kind = getPathKindSync(params.context.absolutePath, false);
|
||||
return buildOutsideBoundaryPathFromContext({
|
||||
boundaryLabel: params.boundaryLabel,
|
||||
context: params.context,
|
||||
kind,
|
||||
});
|
||||
}
|
||||
|
||||
function buildOutsideBoundaryPathFromContext(params: {
|
||||
boundaryLabel: string;
|
||||
context: BoundaryResolutionContext;
|
||||
kind: { exists: boolean; kind: ResolvedBoundaryPathKind };
|
||||
}): ResolvedBoundaryPath {
|
||||
return buildOutsideLexicalBoundaryPath({
|
||||
boundaryLabel: params.boundaryLabel,
|
||||
rootCanonicalPath: params.context.rootCanonicalPath,
|
||||
absolutePath: params.context.absolutePath,
|
||||
canonicalOutsideLexicalPath: params.context.canonicalOutsideLexicalPath,
|
||||
rootPath: params.context.rootPath,
|
||||
kind,
|
||||
kind: params.kind,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,30 @@ export type ExecHost = "sandbox" | "gateway" | "node";
|
||||
export type ExecSecurity = "deny" | "allowlist" | "full";
|
||||
export type ExecAsk = "off" | "on-miss" | "always";
|
||||
|
||||
export function normalizeExecHost(value?: string | null): ExecHost | null {
|
||||
const normalized = value?.trim().toLowerCase();
|
||||
if (normalized === "sandbox" || normalized === "gateway" || normalized === "node") {
|
||||
return normalized;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function normalizeExecSecurity(value?: string | null): ExecSecurity | null {
|
||||
const normalized = value?.trim().toLowerCase();
|
||||
if (normalized === "deny" || normalized === "allowlist" || normalized === "full") {
|
||||
return normalized;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function normalizeExecAsk(value?: string | null): ExecAsk | null {
|
||||
const normalized = value?.trim().toLowerCase();
|
||||
if (normalized === "off" || normalized === "on-miss" || normalized === "always") {
|
||||
return normalized;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export type SystemRunApprovalBinding = {
|
||||
argv: string[];
|
||||
cwd: string | null;
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
import { rejectPendingPairingRequest } from "./pairing-pending.js";
|
||||
import { generatePairingToken, verifyPairingToken } from "./pairing-token.js";
|
||||
|
||||
export type NodePairingPendingRequest = {
|
||||
requestId: string;
|
||||
type NodePairingNodeMetadata = {
|
||||
nodeId: string;
|
||||
displayName?: string;
|
||||
platform?: string;
|
||||
@@ -24,26 +23,18 @@ export type NodePairingPendingRequest = {
|
||||
commands?: string[];
|
||||
permissions?: Record<string, boolean>;
|
||||
remoteIp?: string;
|
||||
};
|
||||
|
||||
export type NodePairingPendingRequest = NodePairingNodeMetadata & {
|
||||
requestId: string;
|
||||
silent?: boolean;
|
||||
isRepair?: boolean;
|
||||
ts: number;
|
||||
};
|
||||
|
||||
export type NodePairingPairedNode = {
|
||||
nodeId: string;
|
||||
export type NodePairingPairedNode = Omit<NodePairingNodeMetadata, "requestId"> & {
|
||||
token: string;
|
||||
displayName?: string;
|
||||
platform?: string;
|
||||
version?: string;
|
||||
coreVersion?: string;
|
||||
uiVersion?: string;
|
||||
deviceFamily?: string;
|
||||
modelIdentifier?: string;
|
||||
caps?: string[];
|
||||
commands?: string[];
|
||||
bins?: string[];
|
||||
permissions?: Record<string, boolean>;
|
||||
remoteIp?: string;
|
||||
createdAtMs: number;
|
||||
approvedAtMs: number;
|
||||
lastConnectedAtMs?: number;
|
||||
|
||||
19
src/infra/parse-finite-number.test.ts
Normal file
19
src/infra/parse-finite-number.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { parseFiniteNumber } from "./parse-finite-number.js";
|
||||
|
||||
describe("parseFiniteNumber", () => {
|
||||
it("returns finite numbers", () => {
|
||||
expect(parseFiniteNumber(42)).toBe(42);
|
||||
});
|
||||
|
||||
it("parses numeric strings", () => {
|
||||
expect(parseFiniteNumber("3.14")).toBe(3.14);
|
||||
});
|
||||
|
||||
it("returns undefined for non-finite or non-numeric values", () => {
|
||||
expect(parseFiniteNumber(Number.NaN)).toBeUndefined();
|
||||
expect(parseFiniteNumber(Number.POSITIVE_INFINITY)).toBeUndefined();
|
||||
expect(parseFiniteNumber("not-a-number")).toBeUndefined();
|
||||
expect(parseFiniteNumber(null)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
12
src/infra/parse-finite-number.ts
Normal file
12
src/infra/parse-finite-number.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export function parseFiniteNumber(value: unknown): number | undefined {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const parsed = Number.parseFloat(value);
|
||||
if (Number.isFinite(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { parseFiniteNumber as parseFiniteNumberish } from "./parse-finite-number.js";
|
||||
import { PROVIDER_LABELS } from "./provider-usage.shared.js";
|
||||
import type { ProviderUsageSnapshot, UsageProviderId } from "./provider-usage.types.js";
|
||||
|
||||
@@ -17,16 +18,7 @@ export async function fetchJson(
|
||||
}
|
||||
|
||||
export function parseFiniteNumber(value: unknown): number | undefined {
|
||||
if (typeof value === "number" && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const parsed = Number.parseFloat(value);
|
||||
if (Number.isFinite(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
return parseFiniteNumberish(value);
|
||||
}
|
||||
|
||||
type BuildUsageHttpErrorSnapshotOptions = {
|
||||
|
||||
Reference in New Issue
Block a user