mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 11:52:55 +00:00
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.
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
|
import { normalizeStringEntriesLower } from "@openclaw/normalization-core/string-normalization";
|
|
import {
|
|
resolveThreadBindingSpawnPolicy,
|
|
supportsAutomaticThreadBindingSpawn,
|
|
} from "../channels/thread-bindings-policy.js";
|
|
import { resolveChannelCapabilities } from "../config/channel-capabilities.js";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { resolveChannelPromptCapabilities } from "./channel-tools.js";
|
|
|
|
const THREAD_BOUND_SUBAGENT_SPAWN_CAPABILITY = "threadbound-subagent-spawn";
|
|
const THREAD_BOUND_ACP_SPAWN_CAPABILITY = "threadbound-acp-spawn";
|
|
|
|
function mergeRuntimeCapabilities(
|
|
base?: readonly string[] | null,
|
|
additions: readonly string[] = [],
|
|
): string[] | undefined {
|
|
const merged = [...(base ?? [])];
|
|
const seen = new Set(normalizeStringEntriesLower(merged));
|
|
|
|
for (const capability of additions) {
|
|
const normalizedCapability = normalizeOptionalLowercaseString(capability);
|
|
if (!normalizedCapability || seen.has(normalizedCapability)) {
|
|
continue;
|
|
}
|
|
seen.add(normalizedCapability);
|
|
merged.push(capability);
|
|
}
|
|
|
|
return merged.length > 0 ? merged : undefined;
|
|
}
|
|
|
|
export function collectRuntimeChannelCapabilities(params: {
|
|
cfg?: OpenClawConfig;
|
|
channel?: string | null;
|
|
accountId?: string | null;
|
|
}): string[] | undefined {
|
|
if (!params.channel) {
|
|
return undefined;
|
|
}
|
|
const threadSpawnCapabilities: string[] = [];
|
|
if (params.cfg && supportsAutomaticThreadBindingSpawn(params.channel)) {
|
|
for (const [kind, capability] of [
|
|
["subagent", THREAD_BOUND_SUBAGENT_SPAWN_CAPABILITY],
|
|
["acp", THREAD_BOUND_ACP_SPAWN_CAPABILITY],
|
|
] as const) {
|
|
const policy = resolveThreadBindingSpawnPolicy({
|
|
cfg: params.cfg,
|
|
channel: params.channel,
|
|
accountId: params.accountId ?? undefined,
|
|
kind,
|
|
});
|
|
if (policy.enabled && policy.spawnEnabled) {
|
|
threadSpawnCapabilities.push(capability);
|
|
}
|
|
}
|
|
}
|
|
return mergeRuntimeCapabilities(
|
|
resolveChannelCapabilities(params),
|
|
params.cfg
|
|
? [...resolveChannelPromptCapabilities(params), ...threadSpawnCapabilities]
|
|
: threadSpawnCapabilities,
|
|
);
|
|
}
|