refactor: extract normalization core package

Extract shared normalization/coercion helpers into private @openclaw/normalization-core workspace package while preserving existing plugin SDK helper subpaths.\n\nAlso keeps direct normalization-core imports internal, wires UI/build/loader resolution, and replaces the slow PR network CodeQL lane with a fast added-line boundary scan while retaining full CodeQL for scheduled/manual runs.\n\nVerification: local moved tests, plugin SDK boundary tests, extension loader tests, agents-support shard, UI build/test, build artifacts, lint, workflow guards, autoreview, and GitHub CI passed on PR head 963d893715.
This commit is contained in:
Peter Steinberger
2026-05-31 01:33:00 +01:00
committed by GitHub
parent 94814f3516
commit 00d8d7ead0
1537 changed files with 3715 additions and 2656 deletions

View File

@@ -7,8 +7,16 @@ queries:
- uses: ./.github/codeql/openclaw-boundary/queries/managed-proxy-runtime-mutation.ql
paths:
- src
- extensions
- src/cli/gateway-cli/run-loop.ts
- src/infra/gateway-lock.ts
- src/infra/jsonl-socket.ts
- src/infra/net
- src/infra/push-apns-http2.ts
- src/infra/ssh-tunnel.ts
- src/proxy-capture
- extensions/codex-supervisor/src/json-rpc-client.ts
- extensions/irc/src
- extensions/qa-lab/src
- packages/net-policy/src
paths-ignore:

View File

@@ -210,6 +210,9 @@ jobs:
else
while IFS= read -r file; do
case "${file}" in
.github/codeql/codeql-network-runtime-boundary-critical-quality.yml|.github/codeql/openclaw-boundary/queries/raw-socket-callsite-classification.ql|.github/codeql/openclaw-boundary/queries/managed-proxy-runtime-mutation.ql)
network_runtime=true
;;
.github/codeql/*|.github/workflows/codeql-critical-quality.yml)
agent=true
channel=true
@@ -222,7 +225,6 @@ jobs:
plugin_sdk_package=true
plugin_sdk_reply=true
provider=true
network_runtime=true
session_diagnostics=true
;;
src/agents/sessions/tools/*)
@@ -304,7 +306,7 @@ jobs:
case "${file}" in
src/**/*.test.ts|src/**/*.test.tsx|extensions/**/*.test.ts|extensions/**/*.test.tsx)
;;
src/*.ts|src/**/*.ts|extensions/*.ts|extensions/**/*.ts|packages/net-policy/src/*|packages/net-policy/src/**/*)
packages/net-policy/src/*|packages/net-policy/src/**/*|src/cli/gateway-cli/run-loop.ts|src/infra/net/*|src/infra/net/**/*|src/infra/ssh-tunnel.ts|src/infra/gateway-lock.ts|src/infra/jsonl-socket.ts|src/infra/push-apns-http2.ts|src/proxy-capture/*|src/proxy-capture/**/*|extensions/codex-supervisor/src/json-rpc-client.ts|extensions/irc/src/*|extensions/qa-lab/src/*)
network_runtime=true
;;
esac
@@ -431,7 +433,33 @@ jobs:
with:
submodules: false
- name: Fast PR network boundary diff scan
if: ${{ github.event_name == 'pull_request' }}
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
added_lines="$(mktemp)"
gh api --paginate "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '
.[]
| select(.filename | test("^(src/cli/gateway-cli/run-loop\\.ts|src/infra/(gateway-lock|jsonl-socket|push-apns-http2|ssh-tunnel)\\.ts|src/infra/net/|src/proxy-capture/|extensions/codex-supervisor/src/json-rpc-client\\.ts|extensions/irc/src/|extensions/qa-lab/src/|packages/net-policy/src/)"))
| .filename as $file
| (.patch // "")
| split("\n")[]
| select(startswith("+") and (startswith("+++") | not))
| "\($file): \(.)"
' > "$added_lines"
if grep -En '(from|require\().*["'\''](node:)?(net|tls|http2)["'\'']|\b(net|tls|http2)\.(connect|createConnection)\b|new Socket\(|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|GLOBAL_AGENT_|OPENCLAW_PROXY_' "$added_lines"; then
echo "Network runtime boundary-sensitive added lines require full CodeQL review." >&2
exit 1
fi
- name: Initialize CodeQL
if: ${{ github.event_name != 'pull_request' }}
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: javascript-typescript
@@ -439,12 +467,14 @@ jobs:
- name: Analyze
id: analyze
if: ${{ github.event_name != 'pull_request' }}
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
output: sarif-results
category: "/codeql-critical-quality/network-runtime-boundary"
- name: Fail on network runtime boundary findings
if: ${{ github.event_name != 'pull_request' }}
env:
SARIF_OUTPUT: sarif-results
run: |

View File

@@ -2,9 +2,15 @@
"extends": "../tsconfig.json",
"compilerOptions": {
"paths": {
"openclaw/extension-api": ["../src/extensionAPI.ts"],
"openclaw/plugin-sdk": ["../dist/plugin-sdk/index.d.ts"],
"openclaw/plugin-sdk/*": ["../dist/plugin-sdk/*.d.ts"],
"openclaw/extension-api": [
"../src/extensionAPI.ts"
],
"openclaw/plugin-sdk": [
"../dist/plugin-sdk/index.d.ts"
],
"openclaw/plugin-sdk/*": [
"../dist/plugin-sdk/*.d.ts"
],
"openclaw/plugin-sdk/reply-payload-testing": [
"../packages/plugin-sdk/dist/src/plugin-sdk/reply-payload-testing.d.ts"
],
@@ -29,9 +35,6 @@
"openclaw/plugin-sdk/plugin-test-contracts": [
"../packages/plugin-sdk/dist/src/plugin-sdk/plugin-test-contracts.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
"openclaw/plugin-sdk/plugin-test-runtime": [
"../packages/plugin-sdk/dist/src/plugin-sdk/plugin-test-runtime.d.ts"
],
@@ -53,10 +56,15 @@
"openclaw/plugin-sdk/testing": [
"../packages/plugin-sdk/dist/src/plugin-sdk/testing.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
"openclaw/plugin-sdk/channel-contract-testing": [
"../packages/plugin-sdk/dist/src/plugin-sdk/channel-contract-testing.d.ts"
],
"openclaw/plugin-sdk/account-id": ["../dist/plugin-sdk/account-id.d.ts"],
"openclaw/plugin-sdk/account-id": [
"../dist/plugin-sdk/account-id.d.ts"
],
"openclaw/plugin-sdk/channel-entry-contract": [
"../dist/plugin-sdk/channel-entry-contract.d.ts"
],
@@ -75,7 +83,9 @@
"openclaw/plugin-sdk/channel-streaming": [
"../dist/plugin-sdk/channel-streaming.d.ts"
],
"openclaw/plugin-sdk/error-runtime": ["../dist/plugin-sdk/error-runtime.d.ts"],
"openclaw/plugin-sdk/error-runtime": [
"../dist/plugin-sdk/error-runtime.d.ts"
],
"openclaw/plugin-sdk/provider-catalog-shared": [
"../dist/plugin-sdk/provider-catalog-shared.d.ts"
],
@@ -85,23 +95,39 @@
"openclaw/plugin-sdk/secret-ref-runtime": [
"../dist/plugin-sdk/secret-ref-runtime.d.ts"
],
"openclaw/plugin-sdk/ssrf-runtime": ["../dist/plugin-sdk/ssrf-runtime.d.ts"],
"@openclaw/qa-channel/api.js": ["../dist/plugin-sdk/extensions/qa-channel/api.d.ts"],
"@openclaw/discord/api.js": ["../dist/plugin-sdk/extensions/discord/api.d.ts"],
"@openclaw/slack/api.js": ["../dist/plugin-sdk/extensions/slack/api.d.ts"],
"@openclaw/whatsapp/api.js": ["../dist/plugin-sdk/extensions/whatsapp/api.d.ts"],
"@openclaw/llm-core": ["../dist/plugin-sdk/packages/llm-core/src/index.d.ts"],
"openclaw/plugin-sdk/ssrf-runtime": [
"../dist/plugin-sdk/ssrf-runtime.d.ts"
],
"@openclaw/qa-channel/api.js": [
"../dist/plugin-sdk/extensions/qa-channel/api.d.ts"
],
"@openclaw/discord/api.js": [
"../dist/plugin-sdk/extensions/discord/api.d.ts"
],
"@openclaw/slack/api.js": [
"../dist/plugin-sdk/extensions/slack/api.d.ts"
],
"@openclaw/whatsapp/api.js": [
"../dist/plugin-sdk/extensions/whatsapp/api.d.ts"
],
"@openclaw/llm-core": [
"../dist/plugin-sdk/packages/llm-core/src/index.d.ts"
],
"@openclaw/llm-core/diagnostics": [
"../dist/plugin-sdk/packages/llm-core/src/utils/diagnostics.d.ts"
],
"@openclaw/llm-core/event-stream": [
"../dist/plugin-sdk/packages/llm-core/src/utils/event-stream.d.ts"
],
"@openclaw/llm-core/types": ["../dist/plugin-sdk/packages/llm-core/src/types.d.ts"],
"@openclaw/llm-core/types": [
"../dist/plugin-sdk/packages/llm-core/src/types.d.ts"
],
"@openclaw/llm-core/validation": [
"../dist/plugin-sdk/packages/llm-core/src/validation.d.ts"
],
"@openclaw/llm-core/*": ["../dist/plugin-sdk/packages/llm-core/src/*.d.ts"],
"@openclaw/llm-core/*": [
"../dist/plugin-sdk/packages/llm-core/src/*.d.ts"
],
"@openclaw/model-catalog-core": [
"../dist/plugin-sdk/packages/model-catalog-core/src/index.d.ts"
],
@@ -234,14 +260,26 @@
"@openclaw/terminal-core/*": [
"../dist/plugin-sdk/packages/terminal-core/src/*.d.ts"
],
"@openclaw/*.js": ["../packages/plugin-sdk/dist/extensions/*.d.ts", "../extensions/*"],
"@openclaw/*": ["../packages/plugin-sdk/dist/extensions/*", "../extensions/*"],
"openclaw/plugin-sdk/qa-channel": ["../dist/plugin-sdk/src/plugin-sdk/qa-channel.d.ts"],
"@openclaw/*.js": [
"../packages/plugin-sdk/dist/extensions/*.d.ts",
"../extensions/*"
],
"@openclaw/*": [
"../packages/plugin-sdk/dist/extensions/*",
"../extensions/*"
],
"openclaw/plugin-sdk/qa-channel": [
"../dist/plugin-sdk/src/plugin-sdk/qa-channel.d.ts"
],
"openclaw/plugin-sdk/qa-channel-protocol": [
"../dist/plugin-sdk/src/plugin-sdk/qa-channel-protocol.d.ts"
],
"openclaw/plugin-sdk/qa-runtime": ["../dist/plugin-sdk/src/plugin-sdk/qa-runtime.d.ts"],
"@openclaw/plugin-sdk/*": ["../dist/plugin-sdk/*.d.ts"]
"openclaw/plugin-sdk/qa-runtime": [
"../dist/plugin-sdk/src/plugin-sdk/qa-runtime.d.ts"
],
"@openclaw/plugin-sdk/*": [
"../dist/plugin-sdk/*.d.ts"
]
}
}
}

View File

@@ -3,9 +3,15 @@
"compilerOptions": {
"rootDir": ".",
"paths": {
"openclaw/extension-api": ["../../src/extensionAPI.ts"],
"openclaw/plugin-sdk": ["../../dist/plugin-sdk/index.d.ts"],
"openclaw/plugin-sdk/*": ["../../dist/plugin-sdk/*.d.ts"],
"openclaw/extension-api": [
"../../src/extensionAPI.ts"
],
"openclaw/plugin-sdk": [
"../../dist/plugin-sdk/index.d.ts"
],
"openclaw/plugin-sdk/*": [
"../../dist/plugin-sdk/*.d.ts"
],
"openclaw/plugin-sdk/reply-payload-testing": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/reply-payload-testing.d.ts"
],
@@ -30,9 +36,6 @@
"openclaw/plugin-sdk/plugin-test-contracts": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/plugin-test-contracts.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
"openclaw/plugin-sdk/plugin-test-runtime": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/plugin-test-runtime.d.ts"
],
@@ -54,10 +57,15 @@
"openclaw/plugin-sdk/testing": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/testing.d.ts"
],
"openclaw/plugin-sdk/plugin-state-test-runtime": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/plugin-state-test-runtime.d.ts"
],
"openclaw/plugin-sdk/channel-contract-testing": [
"../../packages/plugin-sdk/dist/src/plugin-sdk/channel-contract-testing.d.ts"
],
"openclaw/plugin-sdk/account-id": ["../../dist/plugin-sdk/account-id.d.ts"],
"openclaw/plugin-sdk/account-id": [
"../../dist/plugin-sdk/account-id.d.ts"
],
"openclaw/plugin-sdk/channel-entry-contract": [
"../../dist/plugin-sdk/channel-entry-contract.d.ts"
],
@@ -70,29 +78,24 @@
"openclaw/plugin-sdk/channel-streaming": [
"../../dist/plugin-sdk/channel-streaming.d.ts"
],
"openclaw/plugin-sdk/cli-runtime": ["../../dist/plugin-sdk/cli-runtime.d.ts"],
"openclaw/plugin-sdk/error-runtime": [
"../../dist/plugin-sdk/error-runtime.d.ts"
],
"openclaw/plugin-sdk/provider-catalog-shared": [
"../../dist/plugin-sdk/provider-catalog-shared.d.ts"
],
"openclaw/plugin-sdk/provider-env-vars": [
"../../dist/plugin-sdk/provider-env-vars.d.ts"
],
"openclaw/plugin-sdk/provider-entry": [
"../../dist/plugin-sdk/provider-entry.d.ts"
],
"openclaw/plugin-sdk/provider-web-search-contract": [
"../../dist/plugin-sdk/provider-web-search-contract.d.ts"
],
"openclaw/plugin-sdk/secret-ref-runtime": [
"../../dist/plugin-sdk/secret-ref-runtime.d.ts"
],
"openclaw/plugin-sdk/ssrf-runtime": [
"../../dist/plugin-sdk/ssrf-runtime.d.ts"
],
"@openclaw/qa-channel/api.js": ["../../dist/plugin-sdk/extensions/qa-channel/api.d.ts"],
"@openclaw/qa-channel/api.js": [
"../../dist/plugin-sdk/extensions/qa-channel/api.d.ts"
],
"@openclaw/llm-core": [
"../../dist/plugin-sdk/packages/llm-core/src/index.d.ts"
],
@@ -243,23 +246,52 @@
"@openclaw/terminal-core/*": [
"../../dist/plugin-sdk/packages/terminal-core/src/*.d.ts"
],
"@openclaw/*.js": ["../../packages/plugin-sdk/dist/extensions/*.d.ts", "../*"],
"@openclaw/*": ["../*"],
"@openclaw/*.js": [
"../../packages/plugin-sdk/dist/extensions/*.d.ts",
"../*"
],
"@openclaw/*": [
"../*"
],
"openclaw/plugin-sdk/qa-channel": [
"../../dist/plugin-sdk/src/plugin-sdk/qa-channel.d.ts"
],
"openclaw/plugin-sdk/qa-channel-protocol": [
"../../dist/plugin-sdk/src/plugin-sdk/qa-channel-protocol.d.ts"
],
"openclaw/plugin-sdk/qa-runtime": ["../../dist/plugin-sdk/src/plugin-sdk/qa-runtime.d.ts"],
"@openclaw/plugin-sdk/*": ["../../dist/plugin-sdk/*.d.ts"],
"@openclaw/anthropic-vertex/api.js": ["./.boundary-stubs/anthropic-vertex-api.d.ts"],
"@openclaw/ollama/api.js": ["./.boundary-stubs/ollama-api.d.ts"],
"@openclaw/ollama/runtime-api.js": ["./.boundary-stubs/ollama-runtime-api.d.ts"],
"@openclaw/speech-core/runtime-api.js": ["./.boundary-stubs/speech-core-runtime-api.d.ts"]
"openclaw/plugin-sdk/qa-runtime": [
"../../dist/plugin-sdk/src/plugin-sdk/qa-runtime.d.ts"
],
"@openclaw/plugin-sdk/*": [
"../../dist/plugin-sdk/*.d.ts"
],
"openclaw/plugin-sdk/cli-runtime": [
"../../dist/plugin-sdk/cli-runtime.d.ts"
],
"openclaw/plugin-sdk/provider-env-vars": [
"../../dist/plugin-sdk/provider-env-vars.d.ts"
],
"openclaw/plugin-sdk/provider-web-search-contract": [
"../../dist/plugin-sdk/provider-web-search-contract.d.ts"
],
"@openclaw/anthropic-vertex/api.js": [
"./.boundary-stubs/anthropic-vertex-api.d.ts"
],
"@openclaw/ollama/api.js": [
"./.boundary-stubs/ollama-api.d.ts"
],
"@openclaw/ollama/runtime-api.js": [
"./.boundary-stubs/ollama-runtime-api.d.ts"
],
"@openclaw/speech-core/runtime-api.js": [
"./.boundary-stubs/speech-core-runtime-api.d.ts"
]
}
},
"include": ["./*.ts", "./src/**/*.ts"],
"include": [
"./*.ts",
"./src/**/*.ts"
],
"exclude": [
"./**/*.test.ts",
"./dist/**",

View File

@@ -0,0 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asPositiveSafeInteger, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, isFutureDateTimestampMs, nonNegativeSecondsToSafeMilliseconds, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, timestampMsToIsoFileStamp, timestampMsToIsoString } from "./number-coercion.mjs";
import { asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, isRecord, readStringField } from "./record-coerce.mjs";
import { hasNonEmptyString, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, normalizeFastMode, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeStringifiedEntries, normalizeStringifiedOptionalString, readStringValue, resolvePrimaryStringValue } from "./string-coerce.mjs";
import { normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeHyphenSlug, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, sortUniqueStrings, uniqueStrings, uniqueValues } from "./string-normalization.mjs";
export { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asPositiveSafeInteger, asRecord, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, hasNonEmptyString, isFutureDateTimestampMs, isRecord, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, nonNegativeSecondsToSafeMilliseconds, normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeFastMode, normalizeHyphenSlug, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeStringifiedEntries, normalizeStringifiedOptionalString, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, readStringField, readStringValue, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolvePrimaryStringValue, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, sortUniqueStrings, timestampMsToIsoFileStamp, timestampMsToIsoString, uniqueStrings, uniqueValues };

View File

@@ -0,0 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asPositiveSafeInteger, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, isFutureDateTimestampMs, nonNegativeSecondsToSafeMilliseconds, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, timestampMsToIsoFileStamp, timestampMsToIsoString } from "./number-coercion.mjs";
import { asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, isRecord, readStringField } from "./record-coerce.mjs";
import { hasNonEmptyString, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, normalizeFastMode, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeStringifiedEntries, normalizeStringifiedOptionalString, readStringValue, resolvePrimaryStringValue } from "./string-coerce.mjs";
import { normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeHyphenSlug, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, sortUniqueStrings, uniqueStrings, uniqueValues } from "./string-normalization.mjs";
export { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asPositiveSafeInteger, asRecord, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, hasNonEmptyString, isFutureDateTimestampMs, isRecord, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, nonNegativeSecondsToSafeMilliseconds, normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeFastMode, normalizeHyphenSlug, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeStringifiedEntries, normalizeStringifiedOptionalString, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, readStringField, readStringValue, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolvePrimaryStringValue, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, sortUniqueStrings, timestampMsToIsoFileStamp, timestampMsToIsoString, uniqueStrings, uniqueValues };

View File

@@ -0,0 +1,70 @@
//#region packages/normalization-core/src/number-coercion.d.ts
declare function asFiniteNumber(value: unknown): number | undefined;
declare function asFiniteNumberInRange(value: unknown, range: {
min?: number;
max?: number;
minExclusive?: boolean;
maxExclusive?: boolean;
}): number | undefined;
declare function asSafeIntegerInRange(value: unknown, range: {
min?: number;
max?: number;
}): number | undefined;
declare function parseFiniteNumber(value: unknown): number | undefined;
declare function parseStrictInteger(value: unknown): number | undefined;
declare function parseStrictFiniteNumber(value: unknown): number | undefined;
declare function asPositiveSafeInteger(value: unknown): number | undefined;
declare const MAX_TIMER_TIMEOUT_MS = 2147000000;
declare const MAX_TIMER_TIMEOUT_SECONDS: number;
declare const MAX_DATE_TIMESTAMP_MS = 8640000000000000;
declare const UNIX_EPOCH_ISO_STRING = "1970-01-01T00:00:00.000Z";
declare function asDateTimestampMs(value: unknown): number | undefined;
declare function isFutureDateTimestampMs(value: unknown, opts?: {
nowMs?: number;
}): value is number;
declare function timestampMsToIsoString(value: unknown): string | undefined;
declare function resolveDateTimestampMs(value: unknown, fallbackValue?: unknown): number;
declare function resolveTimestampMsToIsoString(value: unknown, fallbackValue?: unknown): string;
declare function timestampMsToIsoFileStamp(value: unknown, fallbackValue?: unknown): string;
declare function clampTimerTimeoutMs(valueMs: unknown, minMs?: number): number | undefined;
declare function clampPositiveTimerTimeoutMs(valueMs: unknown): number | undefined;
declare function resolvePositiveTimerTimeoutMs(valueMs: unknown, fallbackMs: number): number;
declare function resolveTimerTimeoutMs(valueMs: unknown, fallbackMs: number, minMs?: number): number;
declare function addTimerTimeoutGraceMs(timeoutMs: unknown, graceMs?: number): number | undefined;
declare function finiteSecondsToTimerSafeMilliseconds(value: unknown, opts?: {
floorSeconds?: boolean;
}): number | undefined;
declare function resolveIntegerOption(value: unknown, fallback: number, range?: {
min?: number;
max?: number;
}): number;
declare function resolveOptionalIntegerOption(value: unknown, range?: {
min?: number;
max?: number;
}): number | undefined;
declare function resolveNonNegativeIntegerOption(value: unknown, fallback: number): number;
declare function parseStrictPositiveInteger(value: unknown): number | undefined;
declare function parseStrictNonNegativeInteger(value: unknown): number | undefined;
declare function positiveSecondsToSafeMilliseconds(value: unknown): number | undefined;
declare function nonNegativeSecondsToSafeMilliseconds(value: unknown): number | undefined;
declare function resolveExpiresAtMsFromDurationMs(value: unknown, opts?: {
nowMs?: number;
bufferMs?: number;
minRemainingMs?: number;
}): number | undefined;
declare function resolveExpiresAtMsFromDurationSeconds(value: unknown, opts?: {
nowMs?: number;
bufferMs?: number;
minRemainingMs?: number;
}): number | undefined;
declare function resolveExpiresAtMsFromEpochSeconds(value: unknown, opts?: {
bufferMs?: number;
maxMs?: number;
}): number | undefined;
declare function resolveExpiresAtMsFromDurationOrEpoch(value: unknown, opts?: {
nowMs?: number;
relativeSecondsThreshold?: number;
absoluteMillisecondsThreshold?: number;
}): number | undefined;
//#endregion
export { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asPositiveSafeInteger, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, isFutureDateTimestampMs, nonNegativeSecondsToSafeMilliseconds, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, timestampMsToIsoFileStamp, timestampMsToIsoString };

View File

@@ -0,0 +1,178 @@
//#region packages/normalization-core/src/number-coercion.ts
function asFiniteNumber(value) {
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
}
function asFiniteNumberInRange(value, range) {
const number = asFiniteNumber(value);
if (number === void 0) return;
if (range.min !== void 0) {
if (range.minExclusive ? number <= range.min : number < range.min) return;
}
if (range.max !== void 0) {
if (range.maxExclusive ? number >= range.max : number > range.max) return;
}
return number;
}
function asSafeIntegerInRange(value, range) {
if (typeof value !== "number" || !Number.isSafeInteger(value)) return;
if (range.min !== void 0 && value < range.min) return;
if (range.max !== void 0 && value > range.max) return;
return value;
}
function normalizeNumericString(value) {
const trimmed = value.trim();
return trimmed ? trimmed : void 0;
}
function parseFiniteNumber(value) {
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
return parseStrictFiniteNumber(value);
}
function parseStrictInteger(value) {
if (typeof value === "number") return Number.isSafeInteger(value) ? value : void 0;
if (typeof value !== "string") return;
const normalized = normalizeNumericString(value);
if (!normalized || !/^[+-]?\d+$/.test(normalized)) return;
const parsed = Number(normalized);
return Number.isSafeInteger(parsed) ? parsed : void 0;
}
function parseStrictFiniteNumber(value) {
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
if (typeof value !== "string") return;
const normalized = normalizeNumericString(value);
if (!normalized || !/^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:e[+-]?\d+)?$/i.test(normalized)) return;
const parsed = Number(normalized);
return Number.isFinite(parsed) ? parsed : void 0;
}
function asPositiveSafeInteger(value) {
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
}
const MAX_TIMER_TIMEOUT_MS = 2147e6;
const MAX_TIMER_TIMEOUT_SECONDS = Math.floor(MAX_TIMER_TIMEOUT_MS / 1e3);
const MAX_DATE_TIMESTAMP_MS = 864e13;
const UNIX_EPOCH_ISO_STRING = "1970-01-01T00:00:00.000Z";
function asDateTimestampMs(value) {
return asFiniteNumberInRange(value, {
min: -864e13,
max: MAX_DATE_TIMESTAMP_MS
});
}
function isFutureDateTimestampMs(value, opts = {}) {
const timestampMs = asDateTimestampMs(value);
const nowMs = asDateTimestampMs(opts.nowMs ?? Date.now());
return timestampMs !== void 0 && nowMs !== void 0 && timestampMs > nowMs;
}
function timestampMsToIsoString(value) {
const timestampMs = asDateTimestampMs(value);
return timestampMs === void 0 ? void 0 : new Date(timestampMs).toISOString();
}
function resolveDateTimestampMs(value, fallbackValue = Date.now()) {
return asDateTimestampMs(value) ?? asDateTimestampMs(fallbackValue) ?? 0;
}
function resolveTimestampMsToIsoString(value, fallbackValue = Date.now()) {
return timestampMsToIsoString(value) ?? timestampMsToIsoString(fallbackValue) ?? "1970-01-01T00:00:00.000Z";
}
function timestampMsToIsoFileStamp(value, fallbackValue = Date.now()) {
return resolveTimestampMsToIsoString(value, fallbackValue).replaceAll(":", "-");
}
function clampTimerTimeoutMs(valueMs, minMs = 1) {
const value = asFiniteNumber(valueMs);
if (value === void 0) return;
return Math.min(Math.max(Math.floor(value), Math.max(1, Math.floor(minMs))), MAX_TIMER_TIMEOUT_MS);
}
function clampPositiveTimerTimeoutMs(valueMs) {
const value = asFiniteNumber(valueMs);
if (value === void 0 || value <= 0) return;
return clampTimerTimeoutMs(value);
}
function resolvePositiveTimerTimeoutMs(valueMs, fallbackMs) {
return clampPositiveTimerTimeoutMs(valueMs) ?? resolveTimerTimeoutMs(fallbackMs, 1);
}
function resolveTimerTimeoutMs(valueMs, fallbackMs, minMs = 1) {
const value = asFiniteNumber(valueMs) ?? asFiniteNumber(fallbackMs);
const min = Math.max(0, Math.floor(minMs));
if (value === void 0) return min;
return Math.min(Math.max(Math.floor(value), min), MAX_TIMER_TIMEOUT_MS);
}
function addTimerTimeoutGraceMs(timeoutMs, graceMs = 5e3) {
const timeout = asFiniteNumber(timeoutMs);
const grace = asFiniteNumber(graceMs);
if (timeout === void 0 || grace === void 0) return;
const withGrace = timeout + grace;
return Number.isFinite(withGrace) ? clampTimerTimeoutMs(withGrace) : MAX_TIMER_TIMEOUT_MS;
}
function finiteSecondsToTimerSafeMilliseconds(value, opts = {}) {
const seconds = asFiniteNumber(value);
if (seconds === void 0 || seconds <= 0) return;
const boundedSeconds = opts.floorSeconds ? Math.floor(seconds) : seconds;
const milliseconds = Math.floor(boundedSeconds * 1e3);
if (!Number.isFinite(milliseconds) || milliseconds <= 0) return;
return Math.min(milliseconds, MAX_TIMER_TIMEOUT_MS);
}
function resolveIntegerOption(value, fallback, range = {}) {
const floored = Math.floor(typeof value === "number" && Number.isFinite(value) ? value : fallback);
const minBounded = range.min === void 0 ? floored : Math.max(range.min, floored);
return range.max === void 0 ? minBounded : Math.min(range.max, minBounded);
}
function resolveOptionalIntegerOption(value, range = {}) {
if (typeof value !== "number" || !Number.isFinite(value)) return;
return resolveIntegerOption(value, value, range);
}
function resolveNonNegativeIntegerOption(value, fallback) {
return resolveIntegerOption(value, fallback, { min: 0 });
}
function parseStrictPositiveInteger(value) {
const parsed = parseStrictInteger(value);
return parsed !== void 0 && parsed > 0 ? parsed : void 0;
}
function parseStrictNonNegativeInteger(value) {
const parsed = parseStrictInteger(value);
return parsed !== void 0 && parsed >= 0 ? parsed : void 0;
}
function positiveSecondsToSafeMilliseconds(value) {
const seconds = parseStrictPositiveInteger(value);
if (seconds === void 0) return;
const milliseconds = seconds * 1e3;
return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
}
function nonNegativeSecondsToSafeMilliseconds(value) {
const seconds = parseStrictNonNegativeInteger(value);
if (seconds === void 0) return;
const milliseconds = seconds * 1e3;
return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
}
function resolveExpiresAtMsFromDurationMs(value, opts = {}) {
const durationMs = asPositiveSafeInteger(value);
if (durationMs === void 0) return;
const nowMs = asDateTimestampMs(opts.nowMs ?? Date.now());
const bufferMs = asFiniteNumber(opts.bufferMs ?? 0);
if (nowMs === void 0 || bufferMs === void 0) return;
const expiresAt = nowMs + durationMs - bufferMs;
if (!Number.isSafeInteger(expiresAt) || timestampMsToIsoString(expiresAt) === void 0) return;
const minRemainingMs = opts.minRemainingMs;
if (minRemainingMs === void 0) return expiresAt;
const minExpiresAt = nowMs + minRemainingMs;
if (!Number.isSafeInteger(minExpiresAt) || timestampMsToIsoString(minExpiresAt) === void 0) return expiresAt;
return Math.max(expiresAt, minExpiresAt);
}
function resolveExpiresAtMsFromDurationSeconds(value, opts = {}) {
const durationMs = positiveSecondsToSafeMilliseconds(value);
return durationMs === void 0 ? void 0 : resolveExpiresAtMsFromDurationMs(durationMs, opts);
}
function resolveExpiresAtMsFromEpochSeconds(value, opts = {}) {
const epochMs = typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) * 1e3 : positiveSecondsToSafeMilliseconds(value);
if (epochMs === void 0) return;
const expiresAt = epochMs - (opts.bufferMs ?? 0);
if (!Number.isSafeInteger(expiresAt)) return;
if (timestampMsToIsoString(expiresAt) === void 0) return;
const maxMs = opts.maxMs;
return maxMs === void 0 || expiresAt <= maxMs ? expiresAt : void 0;
}
function resolveExpiresAtMsFromDurationOrEpoch(value, opts = {}) {
const parsed = parseStrictPositiveInteger(value);
if (parsed === void 0) return;
if (parsed < (opts.relativeSecondsThreshold ?? 1e9)) return resolveExpiresAtMsFromDurationSeconds(parsed, { nowMs: opts.nowMs });
if (parsed < (opts.absoluteMillisecondsThreshold ?? 0xe8d4a51000)) return resolveExpiresAtMsFromEpochSeconds(parsed);
return asDateTimestampMs(parsed);
}
//#endregion
export { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, MAX_TIMER_TIMEOUT_SECONDS, UNIX_EPOCH_ISO_STRING, addTimerTimeoutGraceMs, asDateTimestampMs, asFiniteNumber, asFiniteNumberInRange, asPositiveSafeInteger, asSafeIntegerInRange, clampPositiveTimerTimeoutMs, clampTimerTimeoutMs, finiteSecondsToTimerSafeMilliseconds, isFutureDateTimestampMs, nonNegativeSecondsToSafeMilliseconds, parseFiniteNumber, parseStrictFiniteNumber, parseStrictInteger, parseStrictNonNegativeInteger, parseStrictPositiveInteger, positiveSecondsToSafeMilliseconds, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationOrEpoch, resolveExpiresAtMsFromDurationSeconds, resolveExpiresAtMsFromEpochSeconds, resolveIntegerOption, resolveNonNegativeIntegerOption, resolveOptionalIntegerOption, resolvePositiveTimerTimeoutMs, resolveTimerTimeoutMs, resolveTimestampMsToIsoString, timestampMsToIsoFileStamp, timestampMsToIsoString };

View File

@@ -0,0 +1,10 @@
//#region packages/normalization-core/src/record-coerce.d.ts
declare function isRecord(value: unknown): value is Record<string, unknown>;
declare function asRecord(value: unknown): Record<string, unknown>;
declare function readStringField(record: Record<string, unknown> | null | undefined, key: string): string | undefined;
declare function asOptionalRecord(value: unknown): Record<string, unknown> | undefined;
declare function asNullableRecord(value: unknown): Record<string, unknown> | null;
declare function asOptionalObjectRecord(value: unknown): Record<string, unknown> | undefined;
declare function asNullableObjectRecord(value: unknown): Record<string, unknown> | null;
//#endregion
export { asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, isRecord, readStringField };

View File

@@ -0,0 +1,25 @@
//#region packages/normalization-core/src/record-coerce.ts
function isRecord(value) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function asRecord(value) {
return typeof value === "object" && value !== null ? value : {};
}
function readStringField(record, key) {
const value = record?.[key];
return typeof value === "string" ? value : void 0;
}
function asOptionalRecord(value) {
return isRecord(value) ? value : void 0;
}
function asNullableRecord(value) {
return isRecord(value) ? value : null;
}
function asOptionalObjectRecord(value) {
return value && typeof value === "object" ? value : void 0;
}
function asNullableObjectRecord(value) {
return value && typeof value === "object" ? value : null;
}
//#endregion
export { asNullableObjectRecord, asNullableRecord, asOptionalObjectRecord, asOptionalRecord, asRecord, isRecord, readStringField };

View File

@@ -0,0 +1,17 @@
//#region packages/normalization-core/src/string-coerce.d.ts
declare function readStringValue(value: unknown): string | undefined;
declare function normalizeNullableString(value: unknown): string | null;
declare function normalizeOptionalString(value: unknown): string | undefined;
declare function normalizeStringifiedOptionalString(value: unknown): string | undefined;
declare function normalizeStringifiedEntries(values?: ReadonlyArray<unknown>): string[];
declare function normalizeOptionalLowercaseString(value: unknown): string | undefined;
declare function normalizeLowercaseStringOrEmpty(value: unknown): string;
declare function normalizeFastMode(raw?: string | boolean | null): boolean | undefined;
declare function lowercasePreservingWhitespace(value: string): string;
declare function localeLowercasePreservingWhitespace(value: string): string;
declare function resolvePrimaryStringValue(value: unknown): string | undefined;
declare function normalizeOptionalThreadValue(value: unknown): string | number | undefined;
declare function normalizeOptionalStringifiedId(value: unknown): string | undefined;
declare function hasNonEmptyString(value: unknown): value is string;
//#endregion
export { hasNonEmptyString, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, normalizeFastMode, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeStringifiedEntries, normalizeStringifiedOptionalString, readStringValue, resolvePrimaryStringValue };

View File

@@ -0,0 +1,72 @@
//#region packages/normalization-core/src/string-coerce.ts
function readStringValue(value) {
return typeof value === "string" ? value : void 0;
}
function normalizeNullableString(value) {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed ? trimmed : null;
}
function normalizeOptionalString(value) {
return normalizeNullableString(value) ?? void 0;
}
function normalizeStringifiedOptionalString(value) {
if (typeof value === "string") return normalizeOptionalString(value);
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return normalizeOptionalString(String(value));
}
function normalizeStringifiedEntries(values) {
return (values ?? []).map((entry) => normalizeStringifiedOptionalString(entry)).filter((entry) => Boolean(entry));
}
function normalizeOptionalLowercaseString(value) {
return normalizeOptionalString(value)?.toLowerCase();
}
function normalizeLowercaseStringOrEmpty(value) {
return normalizeOptionalLowercaseString(value) ?? "";
}
function normalizeFastMode(raw) {
if (typeof raw === "boolean") return raw;
if (!raw) return;
const key = normalizeLowercaseStringOrEmpty(raw);
if ([
"off",
"false",
"no",
"0",
"disable",
"disabled",
"normal"
].includes(key)) return false;
if ([
"on",
"true",
"yes",
"1",
"enable",
"enabled",
"fast"
].includes(key)) return true;
}
function lowercasePreservingWhitespace(value) {
return value.toLowerCase();
}
function localeLowercasePreservingWhitespace(value) {
return value.toLocaleLowerCase();
}
function resolvePrimaryStringValue(value) {
if (typeof value === "string") return normalizeOptionalString(value);
if (!value || typeof value !== "object") return;
return normalizeOptionalString(value.primary);
}
function normalizeOptionalThreadValue(value) {
if (typeof value === "number") return Number.isFinite(value) ? Math.trunc(value) : void 0;
return normalizeOptionalString(value);
}
function normalizeOptionalStringifiedId(value) {
const normalized = normalizeOptionalThreadValue(value);
return normalized == null ? void 0 : String(normalized);
}
function hasNonEmptyString(value) {
return normalizeOptionalString(value) !== void 0;
}
//#endregion
export { hasNonEmptyString, localeLowercasePreservingWhitespace, lowercasePreservingWhitespace, normalizeFastMode, normalizeLowercaseStringOrEmpty, normalizeNullableString, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeOptionalThreadValue, normalizeStringifiedEntries, normalizeStringifiedOptionalString, readStringValue, resolvePrimaryStringValue };

View File

@@ -0,0 +1,21 @@
//#region packages/normalization-core/src/string-normalization.d.ts
declare function normalizeStringEntries(list?: ReadonlyArray<unknown>): string[];
declare function normalizeStringEntriesLower(list?: ReadonlyArray<unknown>): string[];
declare function uniqueValues<T>(values: Iterable<T>): T[];
declare function uniqueStrings(values: Iterable<string>): string[];
declare function sortUniqueStrings(values: Iterable<string>): string[];
declare function normalizeUniqueStringEntries(values?: Iterable<unknown>): string[];
declare function normalizeUniqueStringEntriesLower(values?: Iterable<unknown>): string[];
declare function normalizeSortedUniqueStringEntries(values?: Iterable<unknown>): string[];
declare function normalizeTrimmedStringList(value: unknown): string[];
declare function normalizeUniqueTrimmedStringList(value: unknown): string[];
declare function normalizeSortedUniqueTrimmedStringList(value: unknown): string[];
declare function normalizeOptionalTrimmedStringList(value: unknown): string[] | undefined;
declare function normalizeArrayBackedTrimmedStringList(value: unknown): string[] | undefined;
declare function normalizeSingleOrTrimmedStringList(value: unknown): string[];
declare function normalizeUniqueSingleOrTrimmedStringList(value: unknown): string[];
declare function normalizeCsvOrLooseStringList(value: unknown): string[];
declare function normalizeHyphenSlug(raw?: string | null): string;
declare function normalizeAtHashSlug(raw?: string | null): string;
//#endregion
export { normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeHyphenSlug, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, sortUniqueStrings, uniqueStrings, uniqueValues };

View File

@@ -0,0 +1,75 @@
import { normalizeOptionalLowercaseString, normalizeOptionalString } from "./string-coerce.mjs";
//#region packages/normalization-core/src/string-normalization.ts
function normalizeStringEntries(list) {
return (list ?? []).map((entry) => normalizeOptionalString(String(entry)) ?? "").filter(Boolean);
}
function normalizeStringEntriesLower(list) {
return normalizeStringEntries(list).map((entry) => normalizeOptionalLowercaseString(entry) ?? "");
}
function uniqueValues(values) {
return [...new Set(values)];
}
function uniqueStrings(values) {
return uniqueValues(values);
}
function sortUniqueStrings(values) {
return uniqueStrings(values).toSorted((left, right) => left < right ? -1 : left > right ? 1 : 0);
}
function normalizeUniqueStringEntries(values) {
return uniqueStrings(normalizeStringEntries(values ? [...values] : void 0));
}
function normalizeUniqueStringEntriesLower(values) {
return uniqueStrings(normalizeStringEntriesLower(values ? [...values] : void 0).filter(Boolean));
}
function normalizeSortedUniqueStringEntries(values) {
return sortUniqueStrings(normalizeUniqueStringEntries(values));
}
function normalizeTrimmedStringList(value) {
if (!Array.isArray(value)) return [];
return value.flatMap((entry) => {
const normalized = normalizeOptionalString(entry);
return normalized ? [normalized] : [];
});
}
function normalizeUniqueTrimmedStringList(value) {
return uniqueStrings(normalizeTrimmedStringList(value));
}
function normalizeSortedUniqueTrimmedStringList(value) {
return sortUniqueStrings(normalizeTrimmedStringList(value));
}
function normalizeOptionalTrimmedStringList(value) {
const normalized = normalizeTrimmedStringList(value);
return normalized.length > 0 ? normalized : void 0;
}
function normalizeArrayBackedTrimmedStringList(value) {
if (!Array.isArray(value)) return;
return normalizeTrimmedStringList(value);
}
function normalizeSingleOrTrimmedStringList(value) {
if (Array.isArray(value)) return normalizeTrimmedStringList(value);
const normalized = normalizeOptionalString(value);
return normalized ? [normalized] : [];
}
function normalizeUniqueSingleOrTrimmedStringList(value) {
return uniqueStrings(normalizeSingleOrTrimmedStringList(value));
}
function normalizeCsvOrLooseStringList(value) {
if (Array.isArray(value)) return normalizeStringEntries(value);
if (typeof value === "string") return value.split(",").map((entry) => entry.trim()).filter(Boolean);
return [];
}
function normalizeSlugInput(raw) {
return (normalizeOptionalLowercaseString(raw) ?? "").normalize("NFC");
}
function normalizeHyphenSlug(raw) {
const trimmed = normalizeSlugInput(raw);
if (!trimmed) return "";
return trimmed.replace(/\s+/g, "-").replace(/[^\p{L}\p{M}\p{N}#@._+-]+/gu, "-").replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
}
function normalizeAtHashSlug(raw) {
const trimmed = normalizeSlugInput(raw);
if (!trimmed) return "";
return trimmed.replace(/^[@#]+/, "").replace(/[\s_]+/g, "-").replace(/[^\p{L}\p{M}\p{N}-]+/gu, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
}
//#endregion
export { normalizeArrayBackedTrimmedStringList, normalizeAtHashSlug, normalizeCsvOrLooseStringList, normalizeHyphenSlug, normalizeOptionalTrimmedStringList, normalizeSingleOrTrimmedStringList, normalizeSortedUniqueStringEntries, normalizeSortedUniqueTrimmedStringList, normalizeStringEntries, normalizeStringEntriesLower, normalizeTrimmedStringList, normalizeUniqueSingleOrTrimmedStringList, normalizeUniqueStringEntries, normalizeUniqueStringEntriesLower, normalizeUniqueTrimmedStringList, sortUniqueStrings, uniqueStrings, uniqueValues };

View File

@@ -0,0 +1,41 @@
{
"name": "@openclaw/normalization-core",
"version": "0.0.0-private",
"private": true,
"files": [
"dist"
],
"type": "module",
"main": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
},
"./number-coercion": {
"types": "./dist/number-coercion.d.mts",
"import": "./dist/number-coercion.mjs",
"default": "./dist/number-coercion.mjs"
},
"./record-coerce": {
"types": "./dist/record-coerce.d.mts",
"import": "./dist/record-coerce.mjs",
"default": "./dist/record-coerce.mjs"
},
"./string-coerce": {
"types": "./dist/string-coerce.d.mts",
"import": "./dist/string-coerce.mjs",
"default": "./dist/string-coerce.mjs"
},
"./string-normalization": {
"types": "./dist/string-normalization.d.mts",
"import": "./dist/string-normalization.mjs",
"default": "./dist/string-normalization.mjs"
}
},
"scripts": {
"build": "tsdown src/index.ts src/number-coercion.ts src/record-coerce.ts src/string-coerce.ts src/string-normalization.ts --no-config --platform node --format esm --dts --out-dir dist --clean"
}
}

View File

@@ -0,0 +1,4 @@
export * from "./number-coercion.js";
export * from "./record-coerce.js";
export * from "./string-coerce.js";
export * from "./string-normalization.js";

View File

@@ -14,7 +14,10 @@ describe("record-coerce", () => {
});
it("stays isolated from utils.ts so browser bundles stay Node-free", () => {
const source = readFileSync(path.resolve("src/shared/record-coerce.ts"), "utf8");
const source = readFileSync(
path.resolve("packages/normalization-core/src/record-coerce.ts"),
"utf8",
);
expect(source).not.toContain("../utils.js");
});

View File

@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import { normalizeStringifiedEntries } from "./string-coerce.js";
describe("shared/string-coerce", () => {
describe("normalization-core/string-coerce", () => {
it("normalizes primitive stringified entries", () => {
expect(normalizeStringifiedEntries([" a ", 42, true, 0n, "", " ", null, {}])).toEqual([
"a",

View File

@@ -14,7 +14,7 @@ import {
uniqueStrings,
} from "./string-normalization.js";
describe("shared/string-normalization", () => {
describe("normalization-core/string-normalization", () => {
it("normalizes mixed allow-list entries", () => {
expect(normalizeStringEntries([" a ", 42, "", " ", "z"])).toEqual(["a", "42", "z"]);
expect(normalizeStringEntries([" ok ", null, { toString: () => " obj " }])).toEqual([

View File

@@ -16,6 +16,7 @@
"../../packages/markdown-core/src/**/*.ts",
"../../packages/media-generation-core/src/**/*.ts",
"../../packages/model-catalog-core/src/**/*.ts",
"../../packages/normalization-core/src/**/*.ts",
"../../packages/terminal-core/src/**/*.ts",
"../../src/plugin-sdk/**/*.ts",
"../../src/video-generation/dashscope-compatible.ts",

9
pnpm-lock.yaml generated
View File

@@ -1828,6 +1828,8 @@ importers:
specifier: 2.4.0
version: 2.4.0
packages/normalization-core: {}
packages/plugin-package-contract: {}
packages/plugin-sdk: {}
@@ -1853,10 +1855,10 @@ importers:
specifier: 5.6.2
version: 5.6.2
packages/web-content-core: {}
packages/tool-call-repair: {}
packages/web-content-core: {}
ui:
dependencies:
'@create-markdown/preview':
@@ -1865,6 +1867,9 @@ importers:
'@noble/ed25519':
specifier: 3.1.0
version: 3.1.0
'@openclaw/normalization-core':
specifier: workspace:*
version: link:../packages/normalization-core
dompurify:
specifier: 3.4.6
version: 3.4.6

View File

@@ -51,6 +51,7 @@ export const BUILD_ALL_STEPS = [
"packages/media-understanding-common/package.json",
"packages/terminal-core/package.json",
"packages/model-catalog-core/package.json",
"packages/normalization-core/package.json",
"packages/web-content-core/package.json",
"packages/memory-host-sdk/package.json",
"tsconfig.json",
@@ -61,6 +62,7 @@ export const BUILD_ALL_STEPS = [
"packages/model-catalog-core/src",
"packages/memory-host-sdk/src",
"packages/media-generation-core/src",
"packages/normalization-core/src",
"packages/media-understanding-common/src",
"packages/terminal-core/src",
"packages/web-content-core/src",

View File

@@ -4,7 +4,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { normalizeOptionalString } from "../src/shared/string-coerce.ts";
import { normalizeOptionalString } from "../packages/normalization-core/src/string-coerce.js";
import { readBoundedResponseText as readBoundedResponseTextWithLimit } from "./lib/bounded-response.ts";
import {
maskIdentifier,

View File

@@ -12,7 +12,7 @@ import { z } from "zod";
import { PROTOCOL_VERSION } from "../../dist/gateway/protocol/index.js";
import { formatErrorMessage } from "../../dist/infra/errors.js";
import { rawDataToString } from "../../dist/infra/ws.js";
import { readStringValue } from "../../dist/shared/string-coerce.js";
import { readStringValue } from "../../dist/normalization-core/string-coerce.js";
import { readMcpChannelLimits } from "./mcp-channel-limits.ts";
import { connectMcpWithTimeout } from "./mcp-connect-timeout.ts";
import { waitForWebSocketOpen } from "./mcp-websocket-open.ts";

View File

@@ -2,8 +2,8 @@ import { execFileSync } from "node:child_process";
import { mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { normalizeOptionalString } from "../../packages/normalization-core/src/string-coerce.js";
import { validateExternalCodePluginPackageJson } from "../../packages/plugin-package-contract/src/index.ts";
import { normalizeOptionalString } from "../../src/shared/string-coerce.ts";
import { parseReleaseVersion } from "../openclaw-npm-release-check.ts";
import { resolveNpmPublishPlan } from "./npm-publish-plan.mjs";

View File

@@ -9,6 +9,7 @@ const TSDOWN_PACKAGE_NAMES = [
"media-understanding-common",
"model-catalog-core",
"net-policy",
"normalization-core",
"speech-core",
"terminal-core",
];

View File

@@ -21,6 +21,7 @@ const PLUGIN_SDK_TYPE_INPUTS = [
"packages/memory-host-sdk/src",
"packages/media-generation-core/src",
"packages/media-understanding-common/src",
"packages/normalization-core/src",
"packages/terminal-core/src",
"src/video-generation/dashscope-compatible.ts",
"src/video-generation/types.ts",
@@ -105,6 +106,11 @@ const PACKAGE_DTS_REQUIRED_OUTPUTS = [
"packages/plugin-sdk/dist/packages/model-catalog-core/src/provider-id.d.ts",
"packages/plugin-sdk/dist/packages/model-catalog-core/src/provider-model-id-normalization.d.ts",
"packages/plugin-sdk/dist/packages/model-catalog-core/src/provider-model-id-normalize.d.ts",
"packages/plugin-sdk/dist/packages/normalization-core/src/index.d.ts",
"packages/plugin-sdk/dist/packages/normalization-core/src/number-coercion.d.ts",
"packages/plugin-sdk/dist/packages/normalization-core/src/record-coerce.d.ts",
"packages/plugin-sdk/dist/packages/normalization-core/src/string-coerce.d.ts",
"packages/plugin-sdk/dist/packages/normalization-core/src/string-normalization.d.ts",
"packages/plugin-sdk/dist/packages/terminal-core/src/ansi.d.ts",
"packages/plugin-sdk/dist/packages/terminal-core/src/decorative-emoji.d.ts",
"packages/plugin-sdk/dist/packages/terminal-core/src/health-style.d.ts",

View File

@@ -13,6 +13,7 @@ const RUN_NODE_PACKAGE_SOURCE_ROOTS = [
"packages/markdown-core/src",
"packages/media-generation-core/src",
"packages/media-understanding-common/src",
"packages/normalization-core/src",
"packages/terminal-core/src",
"packages/web-content-core/src",
"packages/net-policy/src",

View File

@@ -44,7 +44,10 @@ const RUNTIME_SHIMS: Partial<Record<string, string>> = {
};
function isBareImportSpecifier(id: string): boolean {
if (id === "@openclaw/model-catalog-core/model-catalog-types") {
if (
id === "@openclaw/model-catalog-core/model-catalog-types" ||
id.startsWith("@openclaw/normalization-core/")
) {
return false;
}
return !id.startsWith(".") && !id.startsWith("/") && !/^[A-Za-z]:[\\/]/u.test(id);

View File

@@ -1,12 +1,12 @@
import { homedir } from "node:os";
import path from "node:path";
import { isKnownCoreToolId } from "../agents/tool-catalog.js";
import { isMutatingToolCall } from "../agents/tool-mutation.js";
import { isPathInside } from "../infra/path-guards.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "../shared/string-coerce.js";
} from "@openclaw/normalization-core/string-coerce";
import { isKnownCoreToolId } from "../agents/tool-catalog.js";
import { isMutatingToolCall } from "../agents/tool-mutation.js";
import { isPathInside } from "../infra/path-guards.js";
import { asRecord } from "./record-shared.js";
const SAFE_SEARCH_TOOL_IDS = new Set(["search", "web_search", "memory_search"]);

View File

@@ -1,5 +1,9 @@
import * as readline from "node:readline";
import type { RequestPermissionRequest, RequestPermissionResponse } from "@agentclientprotocol/sdk";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "@openclaw/normalization-core/string-coerce";
import { sanitizeTerminalText } from "../../packages/terminal-core/src/safe-text.js";
import {
materializeWindowsSpawnProgram,
@@ -9,10 +13,6 @@ import {
listKnownProviderAuthEnvVarNames,
omitEnvKeysCaseInsensitive,
} from "../secrets/provider-env-vars.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "../shared/string-coerce.js";
import { classifyAcpToolApproval, type AcpApprovalClass } from "./approval-classifier.js";
type PermissionOption = RequestPermissionRequest["options"][number];

View File

@@ -11,8 +11,8 @@ import {
type RequestPermissionRequest,
type SessionNotification,
} from "@agentclientprotocol/sdk";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import {
buildAcpClientStripKeys,
resolveAcpClientSpawnEnv,

View File

@@ -1,3 +1,5 @@
import { clampTimerTimeoutMs } from "@openclaw/normalization-core/number-coercion";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
import { resolveRuntimeConfigCacheKey } from "../../config/runtime-snapshot.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
@@ -5,8 +7,6 @@ import { logVerbose } from "../../globals.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { normalizeAgentId } from "../../routing/session-key.js";
import { isAcpSessionKey } from "../../sessions/session-key-utils.js";
import { clampTimerTimeoutMs } from "../../shared/number-coercion.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import {
createRunningTaskRun,
completeTaskRunByRunId,

View File

@@ -1,5 +1,5 @@
import { asNullableRecord } from "../../shared/record-coerce.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { asNullableRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { AcpRuntimeError, withAcpRuntimeErrorBoundary } from "../runtime/errors.js";
import type {
AcpRuntime,

View File

@@ -1,10 +1,10 @@
import { setTimeout as scheduleNativeTimeout } from "node:timers";
import { setTimeout as sleep } from "node:timers/promises";
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { AcpSessionRuntimeOptions, SessionAcpMeta } from "../../config/sessions/types.js";
import { resetHeartbeatWakeStateForTests } from "../../infra/heartbeat-wake.js";
import { MAX_TIMER_TIMEOUT_MS } from "../../shared/number-coercion.js";
import { withTempDir } from "../../test-helpers/temp-dir.js";
import type { AcpRuntime, AcpRuntimeCapabilities } from "../runtime/types.js";

View File

@@ -1,3 +1,4 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import {
canonicalizeMainSessionAlias,
resolveMainSessionKey,
@@ -9,7 +10,6 @@ import {
normalizeMainKey,
parseAgentSessionKey,
} from "../../routing/session-key.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { ACP_ERROR_CODES, AcpRuntimeError } from "../runtime/errors.js";
import type { AcpSessionResolution } from "./manager.types.js";

View File

@@ -1,7 +1,7 @@
import { isAbsolute } from "node:path";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import type { AcpSessionRuntimeOptions, SessionAcpMeta } from "../../config/sessions/types.js";
import { parseStrictPositiveInteger } from "../../infra/parse-finite-number.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { normalizeText } from "../normalize-text.js";
import { AcpRuntimeError } from "../runtime/errors.js";

View File

@@ -10,7 +10,7 @@ import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
readStringValue,
} from "../shared/string-coerce.js";
} from "@openclaw/normalization-core/string-coerce";
import { asRecord } from "./record-shared.js";
type GatewayAttachment = {

View File

@@ -1,4 +1,4 @@
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
function readMetaValue<T>(
meta: Record<string, unknown> | null | undefined,

View File

@@ -1 +1 @@
export { normalizeOptionalString as normalizeText } from "../shared/string-coerce.js";
export { normalizeOptionalString as normalizeText } from "../../packages/normalization-core/src/string-coerce.js";

View File

@@ -1,4 +1,4 @@
import { resolveIntegerOption as resolveSharedIntegerOption } from "../shared/number-coercion.js";
import { resolveIntegerOption as resolveSharedIntegerOption } from "@openclaw/normalization-core/number-coercion";
export function resolveIntegerOption(
value: number | undefined,

View File

@@ -3,7 +3,7 @@ import type {
RequestPermissionRequest,
RequestPermissionResponse,
} from "@agentclientprotocol/sdk";
import { normalizeOptionalString as readNonEmptyString } from "../shared/string-coerce.js";
import { normalizeOptionalString as readNonEmptyString } from "@openclaw/normalization-core/string-coerce";
export type GatewayExecApprovalDecision = "allow-once" | "allow-always" | "deny";

View File

@@ -1,8 +1,8 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import type { SessionAcpMeta } from "../config/sessions/types.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { logVerbose } from "../globals.js";
import { formatErrorMessage } from "../infra/errors.js";
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
import { getAcpSessionManager } from "./control-plane/manager.js";
import { resolveConfiguredAcpBindingSpecBySessionKey } from "./persistent-bindings.resolve.js";
import {

View File

@@ -1,9 +1,9 @@
import { createHash } from "node:crypto";
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
import type { ChannelId } from "../channels/plugins/types.public.js";
import type { SessionBindingRecord } from "../infra/outbound/session-binding-service.js";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "../routing/session-key.js";
import { sanitizeAgentId } from "../routing/session-key.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { normalizeText } from "./normalize-text.js";
import type { AcpRuntimeSessionMode } from "./runtime/types.js";

View File

@@ -1 +1 @@
export { asOptionalRecord as asRecord } from "../shared/record-coerce.js";
export { asOptionalRecord as asRecord } from "@openclaw/normalization-core/record-coerce";

View File

@@ -1,6 +1,6 @@
import { randomUUID } from "node:crypto";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { expect } from "vitest";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { toAcpRuntimeError } from "./errors.js";
import type { AcpRuntime, AcpRuntimeEvent } from "./types.js";

View File

@@ -1,5 +1,5 @@
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
import { resolveGlobalSingleton } from "../../shared/global-singleton.js";
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
import { AcpRuntimeError } from "./errors.js";
import type { AcpRuntime } from "./types.js";

View File

@@ -1,5 +1,5 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import type { SessionAcpIdentity, SessionAcpMeta } from "../../config/sessions/types.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { normalizeText } from "../normalize-text.js";
import { isSessionIdentityPending, resolveSessionIdentityFromMeta } from "./session-identity.js";

View File

@@ -1,3 +1,4 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { getRuntimeConfig } from "../../config/config.js";
import { resolveStorePath } from "../../config/sessions/paths.js";
import { loadSessionStore } from "../../config/sessions/store-load.js";
@@ -9,7 +10,6 @@ import {
} from "../../config/sessions/types.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { parseAgentSessionKey } from "../../routing/session-key.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
let sessionStoreRuntimePromise:
| Promise<typeof import("../../config/sessions/store.runtime.js")>

View File

@@ -2,6 +2,7 @@
import { Readable, Writable } from "node:stream";
import { fileURLToPath } from "node:url";
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import {
GATEWAY_CLIENT_CAPS,
GATEWAY_CLIENT_MODES,
@@ -13,7 +14,6 @@ import { startGatewayClientWhenEventLoopReady } from "../gateway/client-start-re
import { GatewayClient } from "../gateway/client.js";
import { isMainModule } from "../infra/is-main.js";
import { routeLogsToStderr } from "../logging/console.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { createFileAcpEventLedger, resolveDefaultAcpEventLedgerPath } from "./event-ledger.js";
import { readSecretFromFile } from "./secret-file.js";
import { AcpGatewayAgent } from "./translator.js";

View File

@@ -1,5 +1,5 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { SessionEntry } from "../config/sessions/types.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
type AcpSessionInteractionMode = "interactive" | "parent-owned-background";

View File

@@ -1,5 +1,5 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { GatewaySessionRow } from "../gateway/session-utils.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
const SUBAGENT_ROLES = ["orchestrator", "leaf"] as const;
const SUBAGENT_CONTROL_SCOPES = ["children", "none"] as const;

View File

@@ -33,6 +33,8 @@ import type {
ToolCallLocation,
ToolKind,
} from "@agentclientprotocol/sdk";
import { timestampMsToIsoString } from "@openclaw/normalization-core/number-coercion";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { EventFrame } from "../../packages/gateway-protocol/src/index.js";
import { BASE_THINKING_LEVELS } from "../auto-reply/thinking.shared.js";
import type { GatewayClient } from "../gateway/client.js";
@@ -42,8 +44,6 @@ import {
resolveFixedWindowRateLimitInteger,
type FixedWindowRateLimiter,
} from "../infra/fixed-window-rate-limit.js";
import { timestampMsToIsoString } from "../shared/number-coercion.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { shortenHomePath } from "../utils.js";
import {
createInMemoryAcpEventLedger,

View File

@@ -1,5 +1,5 @@
import type { SessionId } from "@agentclientprotocol/sdk";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
import { VERSION } from "../version.js";
const ACP_PROVENANCE_MODE_VALUES = ["off", "meta", "meta+receipt"] as const;

View File

@@ -1,5 +1,5 @@
import { asOptionalRecord } from "../shared/record-coerce.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { asOptionalRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
export type AcceptedSessionSpawn = {
runId: string;

View File

@@ -1,5 +1,7 @@
import { mkdir } from "node:fs/promises";
import path from "node:path";
import { asFiniteNumber } from "@openclaw/normalization-core/number-coercion";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { readAcpSessionEntry } from "../acp/runtime/session-meta.js";
import { resolveSessionFilePath, resolveSessionFilePathOptions } from "../config/sessions/paths.js";
import { onAgentEvent } from "../infra/agent-events.js";
@@ -12,8 +14,6 @@ import { requestHeartbeat } from "../infra/heartbeat-wake.js";
import { appendRegularFile } from "../infra/regular-file.js";
import { enqueueSystemEvent } from "../infra/system-events.js";
import { normalizeAssistantPhase } from "../shared/chat-message-content.js";
import { asFiniteNumber } from "../shared/number-coercion.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { recordTaskRunProgressByRunId } from "../tasks/detached-task-runtime.js";
import type { DeliveryContext } from "../utils/delivery-context.types.js";

View File

@@ -1,5 +1,9 @@
import crypto from "node:crypto";
import fs from "node:fs/promises";
import {
normalizeOptionalLowercaseString,
normalizeOptionalString,
} from "@openclaw/normalization-core/string-coerce";
import { getAcpSessionManager } from "../acp/control-plane/manager.js";
import type { AcpTurnAttachment } from "../acp/control-plane/manager.types.js";
import {
@@ -56,10 +60,6 @@ import {
parseAgentSessionKey,
resolveAgentIdFromSessionKey,
} from "../routing/session-key.js";
import {
normalizeOptionalLowercaseString,
normalizeOptionalString,
} from "../shared/string-coerce.js";
import { createRunningTaskRun } from "../tasks/detached-task-runtime.js";
import { listTasksForOwnerKey } from "../tasks/runtime-internal.js";
import {

View File

@@ -1,7 +1,7 @@
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import { asDateTimestampMs } from "@openclaw/normalization-core/number-coercion";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { coerceSecretRef } from "../config/types.secrets.js";
import { asDateTimestampMs } from "../shared/number-coercion.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import type { AuthProfileCredential, AuthProfileStore } from "./auth-profiles.js";
type AgentApiKeyCredential = { type: "api_key"; key: string };

View File

@@ -1,4 +1,5 @@
import { spawn, type ChildProcess } from "node:child_process";
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { sanitizeHostExecEnv } from "../infra/host-env-security.js";
import { logDebug, logWarn } from "../logger.js";
@@ -8,7 +9,6 @@ import {
} from "../plugin-sdk/windows-spawn.js";
import { setPluginToolMeta } from "../plugins/tools.js";
import { killProcessTree } from "../process/kill-tree.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { loadEmbeddedAgentLspConfig } from "./embedded-agent-lsp.js";
import {
resolveStdioMcpServerLaunchConfig,

View File

@@ -1,9 +1,9 @@
import crypto from "node:crypto";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { logWarn } from "../logger.js";
import { setPluginToolMeta } from "../plugins/tools.js";
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
import {
buildSafeToolName,
normalizeReservedToolNames,

View File

@@ -1,7 +1,7 @@
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
} from "@openclaw/normalization-core/string-coerce";
const TOOL_NAME_SAFE_RE = /[^A-Za-z0-9_-]/g;
export const TOOL_NAME_SEPARATOR = "__";

View File

@@ -11,6 +11,7 @@ import type {
jsonSchemaValidator,
} from "@modelcontextprotocol/sdk/validation/types.js";
import { redactSensitiveUrlLikeString } from "@openclaw/net-policy/redact-sensitive-url";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { Compile } from "typebox/compile";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { logWarn } from "../logger.js";
@@ -20,7 +21,6 @@ import {
findJsonSchemaShapeError,
normalizeJsonSchemaForTypeBox,
} from "../shared/json-schema-defaults.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { sanitizeServerName } from "./agent-bundle-mcp-names.js";
import type {
McpCatalogTool,

View File

@@ -1,3 +1,4 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { sanitizeForLog } from "../../packages/terminal-core/src/ansi.js";
import { resolveInlineAgentImageAttachments } from "../auto-reply/reply/agent-turn-attachments.js";
import { sanitizePendingFinalDeliveryText } from "../auto-reply/reply/pending-final-delivery.js";
@@ -46,7 +47,6 @@ import {
} from "../sessions/model-overrides.js";
import { resolveSendPolicy } from "../sessions/send-policy.js";
import { createLazyImportLoader } from "../shared/lazy-promise.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/discovery/agent-filter.js";
import type { getRemoteSkillEligibility } from "../skills/runtime/remote.js";
import type { resolveReusableWorkspaceSkillSnapshot } from "../skills/runtime/session-snapshot.js";

View File

@@ -1,9 +1,9 @@
import fs from "node:fs";
import path from "node:path";
import { lowercasePreservingWhitespace } from "@openclaw/normalization-core/string-coerce";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { isPathInside } from "../infra/path-guards.js";
import { normalizeAgentId } from "../routing/session-key.js";
import { lowercasePreservingWhitespace } from "../shared/string-coerce.js";
import { listAgentEntries, resolveAgentWorkspaceDir } from "./agent-scope.js";
function normalizeWorkspacePathForComparison(input: string): string {

View File

@@ -1,6 +1,6 @@
import { localeLowercasePreservingWhitespace } from "@openclaw/normalization-core/string-coerce";
import { uniqueStrings } from "@openclaw/normalization-core/string-normalization";
import { extractKeywords, isQueryStopWordToken } from "../../memory-host-sdk/query.js";
import { localeLowercasePreservingWhitespace } from "../../shared/string-coerce.js";
import { uniqueStrings } from "../../shared/string-normalization.js";
import type { CompactionSummarizationInstructions } from "../compaction.js";
import { wrapUntrustedPromptDataBlock } from "../sanitize-for-prompt.js";

View File

@@ -1,4 +1,4 @@
import { normalizeLowercaseStringOrEmpty } from "../../../shared/string-coerce.js";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { compileGlobPatterns, matchesAnyGlobPattern } from "../../glob-pattern.js";
import type { ContextPruningToolMatch } from "./settings.js";

View File

@@ -1,8 +1,8 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
import { describe, expect, it, vi } from "vitest";
import { MAX_DATE_TIMESTAMP_MS } from "../shared/number-coercion.js";
import { resolveAgentCredentialMapFromStore } from "./agent-auth-credentials.js";
import {
addEnvBackedAgentCredentials,

View File

@@ -1,4 +1,5 @@
import path from "node:path";
import { readStringValue } from "@openclaw/normalization-core/string-coerce";
import { resolveStateDir } from "../config/paths.js";
import type {
AgentContextLimitsConfig,
@@ -6,7 +7,6 @@ import type {
} from "../config/types.agent-defaults.js";
import type { OpenClawConfig } from "../config/types.js";
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../routing/session-key.js";
import { readStringValue } from "../shared/string-coerce.js";
import { resolveUserPath } from "../utils.js";
import { resolveDefaultAgentWorkspaceDir } from "./workspace-default.js";

View File

@@ -3,6 +3,12 @@ import path from "node:path";
import { resolveAgentModelFallbackValues } from "../config/model-input.js";
import { hasSessionAutoModelFallbackProvenance } from "../config/sessions/model-override-provenance.js";
export { hasSessionAutoModelFallbackProvenance } from "../config/sessions/model-override-provenance.js";
import {
lowercasePreservingWhitespace,
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
resolvePrimaryStringValue,
} from "@openclaw/normalization-core/string-coerce";
import type { SessionEntry } from "../config/sessions/types.js";
import type { AgentDefaultsConfig } from "../config/types.agent-defaults.js";
import type { AgentModelConfig } from "../config/types.agents-shared.js";
@@ -15,12 +21,6 @@ import {
parseAgentSessionKey,
resolveAgentIdFromSessionKey,
} from "../routing/session-key.js";
import {
lowercasePreservingWhitespace,
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
resolvePrimaryStringValue,
} from "../shared/string-coerce.js";
import { resolveEffectiveAgentSkillFilter } from "../skills/discovery/agent-filter.js";
import { resolveUserPath } from "../utils.js";
import {

View File

@@ -1,13 +1,13 @@
import { isRecord as isSchemaRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { uniqueValues } from "@openclaw/normalization-core/string-normalization";
import type { TSchema } from "typebox";
import type { ModelCompatConfig } from "../config/types.models.js";
import {
resolveUnsupportedToolSchemaKeywords,
shouldOmitEmptyArrayItems,
} from "../plugins/provider-model-compat.js";
import { isRecord as isSchemaRecord } from "../shared/record-coerce.js";
import { stripUnsupportedSchemaKeywords } from "../shared/schema-keyword-strip.js";
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
import { uniqueValues } from "../shared/string-normalization.js";
import { cleanSchemaForGemini } from "./schema/clean-for-gemini.js";
export type ToolParameterSchemaOptions = {

View File

@@ -1,5 +1,6 @@
import os from "node:os";
import path from "node:path";
import { addTimerTimeoutGraceMs } from "@openclaw/normalization-core/number-coercion";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { ToolLoopDetectionConfig } from "../config/types.tools.js";
import {
@@ -35,7 +36,6 @@ import {
type PluginHookToolKind,
} from "../plugins/types.js";
import { createLazyRuntimeSurface } from "../shared/lazy-runtime.js";
import { addTimerTimeoutGraceMs } from "../shared/number-coercion.js";
import {
resolveSkillTelemetrySource,
resolveSkillTelemetrySourceValue,

View File

@@ -1,4 +1,4 @@
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
const TOOL_DENY_BY_MESSAGE_PROVIDER: Readonly<Record<string, readonly string[]>> = {
"discord-voice": ["tts"],

View File

@@ -1,4 +1,12 @@
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "@openclaw/normalization-core/string-coerce";
import {
normalizeUniqueSingleOrTrimmedStringList,
uniqueStrings,
} from "@openclaw/normalization-core/string-normalization";
import { getLoadedChannelPlugin } from "../channels/plugins/index.js";
import { resolveSessionConversation } from "../channels/plugins/session-conversation.js";
import { DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH } from "../config/agent-limits.js";
@@ -11,14 +19,6 @@ import {
parseRawSessionConversationRef,
parseThreadSessionSuffix,
} from "../sessions/session-key-utils.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import {
normalizeUniqueSingleOrTrimmedStringList,
uniqueStrings,
} from "../shared/string-normalization.js";
import { normalizeMessageChannel } from "../utils/message-channel.js";
import { resolveAgentConfig, resolveAgentIdFromSessionKey } from "./agent-scope.js";
import type { AnyAgentTool } from "./agent-tools.types.js";

View File

@@ -1,4 +1,8 @@
import path from "node:path";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "@openclaw/normalization-core/string-coerce";
import type { SourceReplyDeliveryMode } from "../auto-reply/get-reply-options.types.js";
import { HEARTBEAT_RESPONSE_TOOL_NAME } from "../auto-reply/heartbeat-tool-response.js";
import type { InboundEventKind } from "../channels/inbound-event/kind.js";
@@ -17,10 +21,6 @@ import { resolveMergedSafeBinProfileFixtures } from "../infra/exec-safe-bin-runt
import { logWarn } from "../logger.js";
import { getPluginToolMeta } from "../plugins/tools.js";
import { createLazyImportLoader } from "../shared/lazy-promise.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import type { SkillSnapshot } from "../skills/types.js";
import { resolveGatewayMessageChannel } from "../utils/message-channel.js";
import { resolveAgentConfig } from "./agent-scope.js";

View File

@@ -1,10 +1,10 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { getEnvApiKey } from "../llm/env-api-keys.js";
import { calculateCost } from "../llm/model-utils.js";
import type { AnthropicOptions } from "../llm/providers/anthropic.js";
import type { Context, Model, SimpleStreamOptions, ThinkingLevel } from "../llm/types.js";
import { parseStreamingJson } from "../llm/utils/json-parse.js";
import { MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "../shared/assistant-error-format.js";
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
import {
applyAnthropicPayloadPolicyToParams,
resolveAnthropicPayloadPolicy,

View File

@@ -1,3 +1,4 @@
import { normalizeUniqueStringEntries } from "@openclaw/normalization-core/string-normalization";
import { sleepWithAbort } from "../infra/backoff.js";
import { formatErrorMessage } from "../infra/errors.js";
import {
@@ -7,7 +8,6 @@ import {
shouldRetrySameKeyProviderOperation,
type TransientProviderRetryConfig,
} from "../provider-runtime/operation-retry.js";
import { normalizeUniqueStringEntries } from "../shared/string-normalization.js";
import { collectProviderApiKeys, isApiKeyRateLimitError } from "./live-auth-keys.js";
type ApiKeyRetryParams = {

View File

@@ -1,5 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { MAX_DATE_TIMESTAMP_MS } from "../shared/number-coercion.js";
import type { OAuthCredential } from "./auth-profiles/types.js";
const { readCodexCliCredentialsCachedMock } = vi.hoisted(() => ({

View File

@@ -2,9 +2,9 @@ import {
findNormalizedProviderValue,
normalizeProviderId,
} from "@openclaw/model-catalog-core/provider-id";
import { asDateTimestampMs } from "@openclaw/normalization-core/number-coercion";
import { normalizeUniqueStringEntries } from "@openclaw/normalization-core/string-normalization";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { asDateTimestampMs } from "../shared/number-coercion.js";
import { normalizeUniqueStringEntries } from "../shared/string-normalization.js";
import {
DEFAULT_OAUTH_REFRESH_MARGIN_MS,
type AuthCredentialReasonCode,

View File

@@ -1,5 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
import { coerceSecretRef, normalizeSecretInputString } from "../../config/types.secrets.js";
import { MAX_DATE_TIMESTAMP_MS } from "../../shared/number-coercion.js";
import type { AuthProfileCredential, OAuthCredential } from "./types.js";
export type AuthCredentialReasonCode =

View File

@@ -1,5 +1,5 @@
import { normalizeTrimmedStringList } from "@openclaw/normalization-core/string-normalization";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { normalizeTrimmedStringList } from "../../shared/string-normalization.js";
import {
resolveExternalCliAuthScopeFromConfig,
type ExternalCliAuthScope,

View File

@@ -1,5 +1,5 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import type { AuthProfileStore } from "./types.js";
function resolveStoredMetadata(store: AuthProfileStore | undefined, profileId: string) {

View File

@@ -1,5 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
import { describe, expect, it } from "vitest";
import { MAX_DATE_TIMESTAMP_MS } from "../../shared/number-coercion.js";
import {
isSafeToCopyOAuthIdentity,
isSameOAuthIdentity,

View File

@@ -1,4 +1,4 @@
import { asDateTimestampMs } from "../../shared/number-coercion.js";
import { asDateTimestampMs } from "@openclaw/normalization-core/number-coercion";
import type { AuthProfileCredential, OAuthCredential } from "./types.js";
export function normalizeAuthIdentityToken(value: string | undefined): string | undefined {

View File

@@ -1,3 +1,4 @@
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
import { getRuntimeConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { coerceSecretRef } from "../../config/types.secrets.js";
@@ -13,7 +14,6 @@ import {
refreshProviderOAuthCredentialWithPlugin,
} from "../../plugins/provider-runtime.runtime.js";
import { resolveSecretRefString, type SecretRefResolveCache } from "../../secrets/resolve.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { normalizeOptionalSecretInput } from "../../utils/normalize-secret-input.js";
import { refreshChutesTokens } from "../chutes-oauth.js";
import { resolveProviderIdForAuth } from "../provider-auth-aliases.js";

View File

@@ -1,9 +1,9 @@
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import { isRecord } from "@openclaw/normalization-core/record-coerce";
import { uniqueStrings } from "@openclaw/normalization-core/string-normalization";
import { resolveOAuthPath } from "../../config/paths.js";
import { coerceSecretRef } from "../../config/types.secrets.js";
import { loadJsonFile } from "../../infra/json-file.js";
import { isRecord } from "../../shared/record-coerce.js";
import { uniqueStrings } from "../../shared/string-normalization.js";
import { asBoolean } from "../../utils/boolean.js";
import { AUTH_STORE_VERSION, log } from "./constants.js";
import {

View File

@@ -1,4 +1,4 @@
import { uniqueStrings } from "../../shared/string-normalization.js";
import { uniqueStrings } from "@openclaw/normalization-core/string-normalization";
import { resolveProviderIdForAuth } from "../provider-auth-aliases.js";
import type { AuthProfileStore } from "./types.js";

View File

@@ -2,7 +2,7 @@ import {
findNormalizedProviderKey,
normalizeProviderId,
} from "@openclaw/model-catalog-core/provider-id";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization";
import { normalizeSecretInput } from "../../utils/normalize-secret-input.js";
import { resolveProviderIdForAuth } from "../provider-auth-aliases.js";
import { dedupeProfileIds, listProfilesForProvider } from "./profile-list.js";

View File

@@ -1,11 +1,11 @@
import fs from "node:fs";
import { isDeepStrictEqual } from "node:util";
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import { asFiniteNumber } from "@openclaw/normalization-core/number-coercion";
import { isRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { normalizeTrimmedStringList } from "@openclaw/normalization-core/string-normalization";
import { loadJsonFile, repairJsonFilePermissions, saveJsonFile } from "../../infra/json-file.js";
import { asFiniteNumber } from "../../shared/number-coercion.js";
import { isRecord } from "../../shared/record-coerce.js";
import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { normalizeTrimmedStringList } from "../../shared/string-normalization.js";
import { AUTH_STORE_VERSION } from "./constants.js";
import { resolveAuthStatePath } from "./paths.js";
import type {

View File

@@ -1,12 +1,12 @@
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { createSubsystemLogger } from "../../logging/subsystem.js";
import {
asDateTimestampMs,
isFutureDateTimestampMs,
positiveSecondsToSafeMilliseconds,
resolveExpiresAtMsFromEpochSeconds,
} from "../../shared/number-coercion.js";
} from "@openclaw/normalization-core/number-coercion";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { createSubsystemLogger } from "../../logging/subsystem.js";
import { resolveProviderRequestHeaders } from "../provider-request-config.js";
import { logAuthProfileFailureStateChange } from "./state-observation.js";

View File

@@ -2,8 +2,8 @@ import { randomUUID } from "node:crypto";
import {
isFutureDateTimestampMs,
resolveExpiresAtMsFromDurationMs,
} from "../shared/number-coercion.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
} from "@openclaw/normalization-core/number-coercion";
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import type { ExecElevatedDefaults } from "./bash-tools.exec-types.js";
const EXEC_APPROVAL_FOLLOWUP_IDEMPOTENCY_PREFIX = "exec-approval-followup:";

View File

@@ -1,13 +1,13 @@
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "@openclaw/normalization-core/string-coerce";
import {
resolveExternalBestEffortDeliveryTarget,
type ExternalBestEffortDeliveryTarget,
} from "../infra/outbound/best-effort-delivery.js";
import { sendMessage } from "../infra/outbound/message.js";
import { isCronSessionKey, isSubagentSessionKey } from "../sessions/session-key-utils.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "../shared/string-coerce.js";
import { isGatewayMessageChannel, normalizeMessageChannel } from "../utils/message-channel.js";
import { buildExecApprovalFollowupIdempotencyKey } from "./bash-tools.exec-approval-followup-state.js";
import { sanitizeUserFacingText } from "./embedded-agent-helpers/sanitize-user-facing-text.js";

View File

@@ -1,3 +1,11 @@
import {
asDateTimestampMs,
resolveExpiresAtMsFromDurationMs,
} from "@openclaw/normalization-core/number-coercion";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString as parseString,
} from "@openclaw/normalization-core/string-coerce";
import type {
ExecApprovalCommandSpan,
ExecAsk,
@@ -10,11 +18,6 @@ import {
POSIX_SHELL_WRAPPERS,
resolveShellWrapperTransportArgv,
} from "../infra/shell-wrapper-resolution.js";
import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "../shared/number-coercion.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString as parseString,
} from "../shared/string-coerce.js";
import {
DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS,
DEFAULT_APPROVAL_TIMEOUT_MS,

View File

@@ -1,3 +1,5 @@
import { isRecord } from "@openclaw/normalization-core/record-coerce";
import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization";
import { describeInterpreterInlineEval } from "../infra/command-analysis/inline-eval.js";
import { detectPolicyInlineEval } from "../infra/command-analysis/policy.js";
import {
@@ -20,8 +22,6 @@ import {
type ExecAutoReviewInput,
} from "../infra/exec-auto-review.js";
import type { SafeBinProfile } from "../infra/exec-safe-bin-policy.js";
import { isRecord } from "../shared/record-coerce.js";
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { INTERNAL_MESSAGE_CHANNEL, normalizeMessageChannel } from "../utils/message-channel.js";
import { markBackgrounded, tail } from "./bash-process-registry.js";
import {

View File

@@ -1,4 +1,5 @@
import crypto from "node:crypto";
import { normalizeNullableString } from "@openclaw/normalization-core/string-coerce";
import {
describeInterpreterInlineEval,
type InterpreterInlineEvalHit,
@@ -25,7 +26,6 @@ import {
formatExecCommand,
resolveSystemRunCommandRequest,
} from "../infra/system-run-command.js";
import { normalizeNullableString } from "../shared/string-coerce.js";
import { addSafeTimeoutDelayGraceMs } from "../utils/timer-delay.js";
import type { ExecuteNodeHostCommandParams } from "./bash-tools.exec-host-node.types.js";
import { renderExecOutputText } from "./bash-tools.exec-output.js";

View File

@@ -1,5 +1,5 @@
import { MAX_DATE_TIMESTAMP_MS } from "@openclaw/normalization-core/number-coercion";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { MAX_DATE_TIMESTAMP_MS } from "../shared/number-coercion.js";
import {
consumeExecApprovalFollowupRuntimeHandoff,
registerExecApprovalFollowupRuntimeHandoff,

Some files were not shown because too many files have changed in this diff Show More