fix(ui): unblock docker onboarding build

This commit is contained in:
Peter Steinberger
2026-02-19 16:32:14 +01:00
parent 30e36c30d4
commit 3077c35831
7 changed files with 241 additions and 22 deletions

View File

@@ -0,0 +1,121 @@
export type ToolProfileId = "minimal" | "coding" | "messaging" | "full";
type ToolProfilePolicy = {
allow?: string[];
deny?: string[];
};
const TOOL_NAME_ALIASES: Record<string, string> = {
bash: "exec",
"apply-patch": "apply_patch",
};
export const TOOL_GROUPS: Record<string, string[]> = {
// NOTE: Keep canonical (lowercase) tool names here.
"group:memory": ["memory_search", "memory_get"],
"group:web": ["web_search", "web_fetch"],
// Basic workspace/file tools
"group:fs": ["read", "write", "edit", "apply_patch"],
// Host/runtime execution tools
"group:runtime": ["exec", "process"],
// Session management tools
"group:sessions": [
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"subagents",
"session_status",
],
// UI helpers
"group:ui": ["browser", "canvas"],
// Automation + infra
"group:automation": ["cron", "gateway"],
// Messaging surface
"group:messaging": ["message"],
// Nodes + device tools
"group:nodes": ["nodes"],
// All OpenClaw native tools (excludes provider plugins).
"group:openclaw": [
"browser",
"canvas",
"nodes",
"cron",
"message",
"gateway",
"agents_list",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"subagents",
"session_status",
"memory_search",
"memory_get",
"web_search",
"web_fetch",
"image",
],
};
const TOOL_PROFILES: Record<ToolProfileId, ToolProfilePolicy> = {
minimal: {
allow: ["session_status"],
},
coding: {
allow: ["group:fs", "group:runtime", "group:sessions", "group:memory", "image"],
},
messaging: {
allow: [
"group:messaging",
"sessions_list",
"sessions_history",
"sessions_send",
"session_status",
],
},
full: {},
};
export function normalizeToolName(name: string) {
const normalized = name.trim().toLowerCase();
return TOOL_NAME_ALIASES[normalized] ?? normalized;
}
export function normalizeToolList(list?: string[]) {
if (!list) {
return [];
}
return list.map(normalizeToolName).filter(Boolean);
}
export function expandToolGroups(list?: string[]) {
const normalized = normalizeToolList(list);
const expanded: string[] = [];
for (const value of normalized) {
const group = TOOL_GROUPS[value];
if (group) {
expanded.push(...group);
continue;
}
expanded.push(value);
}
return Array.from(new Set(expanded));
}
export function resolveToolProfilePolicy(profile?: string): ToolProfilePolicy | undefined {
if (!profile) {
return undefined;
}
const resolved = TOOL_PROFILES[profile as ToolProfileId];
if (!resolved) {
return undefined;
}
if (!resolved.allow && !resolved.deny) {
return undefined;
}
return {
allow: resolved.allow ? [...resolved.allow] : undefined,
deny: resolved.deny ? [...resolved.deny] : undefined,
};
}

View File

@@ -1,4 +1,3 @@
import { createRequire } from "node:module";
import util from "node:util";
import type { OpenClawConfig } from "../config/types.js";
import { isVerbose } from "../globals.js";
@@ -16,14 +15,37 @@ type ConsoleSettings = {
};
export type ConsoleLoggerSettings = ConsoleSettings;
const requireConfig = createRequire(import.meta.url);
function resolveNodeRequire(): ((id: string) => NodeJS.Require) | null {
const getBuiltinModule = (
process as NodeJS.Process & {
getBuiltinModule?: (id: string) => unknown;
}
).getBuiltinModule;
if (typeof getBuiltinModule !== "function") {
return null;
}
try {
const moduleNamespace = getBuiltinModule("module") as {
createRequire?: (id: string) => NodeJS.Require;
};
return typeof moduleNamespace.createRequire === "function"
? moduleNamespace.createRequire
: null;
} catch {
return null;
}
}
const requireConfig = resolveNodeRequire()?.(import.meta.url) ?? null;
type ConsoleConfigLoader = () => OpenClawConfig["logging"] | undefined;
const loadConfigFallbackDefault: ConsoleConfigLoader = () => {
try {
const loaded = requireConfig("../config/config.js") as {
loadConfig?: () => OpenClawConfig;
};
return loaded.loadConfig?.().logging;
const loaded = requireConfig?.("../config/config.js") as
| {
loadConfig?: () => OpenClawConfig;
}
| undefined;
return loaded?.loadConfig?.().logging;
} catch {
return undefined;
}

View File

@@ -1,5 +1,4 @@
import fs from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";
import { Logger as TsLogger } from "tslog";
import type { OpenClawConfig } from "../config/types.js";
@@ -16,7 +15,28 @@ const LOG_PREFIX = "openclaw";
const LOG_SUFFIX = ".log";
const MAX_LOG_AGE_MS = 24 * 60 * 60 * 1000; // 24h
const requireConfig = createRequire(import.meta.url);
function resolveNodeRequire(): ((id: string) => NodeJS.Require) | null {
const getBuiltinModule = (
process as NodeJS.Process & {
getBuiltinModule?: (id: string) => unknown;
}
).getBuiltinModule;
if (typeof getBuiltinModule !== "function") {
return null;
}
try {
const moduleNamespace = getBuiltinModule("module") as {
createRequire?: (id: string) => NodeJS.Require;
};
return typeof moduleNamespace.createRequire === "function"
? moduleNamespace.createRequire
: null;
} catch {
return null;
}
}
const requireConfig = resolveNodeRequire()?.(import.meta.url) ?? null;
export type LoggerSettings = {
level?: LogLevel;
@@ -55,10 +75,12 @@ function resolveSettings(): ResolvedSettings {
(loggingState.overrideSettings as LoggerSettings | null) ?? readLoggingConfig();
if (!cfg) {
try {
const loaded = requireConfig("../config/config.js") as {
loadConfig?: () => OpenClawConfig;
};
cfg = loaded.loadConfig?.().logging;
const loaded = requireConfig?.("../config/config.js") as
| {
loadConfig?: () => OpenClawConfig;
}
| undefined;
cfg = loaded?.loadConfig?.().logging;
} catch {
cfg = undefined;
}

View File

@@ -1,7 +1,27 @@
import { createRequire } from "node:module";
import type { OpenClawConfig } from "../config/config.js";
const requireConfig = createRequire(import.meta.url);
function resolveNodeRequire(): ((id: string) => NodeJS.Require) | null {
const getBuiltinModule = (
process as NodeJS.Process & {
getBuiltinModule?: (id: string) => unknown;
}
).getBuiltinModule;
if (typeof getBuiltinModule !== "function") {
return null;
}
try {
const moduleNamespace = getBuiltinModule("module") as {
createRequire?: (id: string) => NodeJS.Require;
};
return typeof moduleNamespace.createRequire === "function"
? moduleNamespace.createRequire
: null;
} catch {
return null;
}
}
const requireConfig = resolveNodeRequire()?.(import.meta.url) ?? null;
export type RedactSensitiveMode = "off" | "tools";
@@ -110,10 +130,12 @@ function redactText(text: string, patterns: RegExp[]): string {
function resolveConfigRedaction(): RedactOptions {
let cfg: OpenClawConfig["logging"] | undefined;
try {
const loaded = requireConfig("../config/config.js") as {
loadConfig?: () => OpenClawConfig;
};
cfg = loaded.loadConfig?.().logging;
const loaded = requireConfig?.("../config/config.js") as
| {
loadConfig?: () => OpenClawConfig;
}
| undefined;
cfg = loaded?.loadConfig?.().logging;
} catch {
cfg = undefined;
}

View File

@@ -1,4 +1,3 @@
import { inspect } from "node:util";
import { Chalk } from "chalk";
import type { Logger as TsLogger } from "tslog";
import { CHAT_CHANNEL_ORDER } from "../channels/registry.js";
@@ -36,6 +35,39 @@ function shouldLogToConsole(level: LogLevel, settings: { level: LogLevel }): boo
type ChalkInstance = InstanceType<typeof Chalk>;
const inspectValue: ((value: unknown) => string) | null = (() => {
const getBuiltinModule = (
process as NodeJS.Process & {
getBuiltinModule?: (id: string) => unknown;
}
).getBuiltinModule;
if (typeof getBuiltinModule !== "function") {
return null;
}
try {
const utilNamespace = getBuiltinModule("util") as {
inspect?: (value: unknown) => string;
};
return typeof utilNamespace.inspect === "function" ? utilNamespace.inspect : null;
} catch {
return null;
}
})();
function formatRuntimeArg(arg: unknown): string {
if (typeof arg === "string") {
return arg;
}
if (inspectValue) {
return inspectValue(arg);
}
try {
return JSON.stringify(arg);
} catch {
return String(arg);
}
}
function isRichConsoleEnv(): boolean {
const term = (process.env.TERM ?? "").toLowerCase();
if (process.env.COLORTERM || process.env.TERM_PROGRAM) {
@@ -323,7 +355,7 @@ export function runtimeForLogger(
): RuntimeEnv {
const formatArgs = (...args: unknown[]) =>
args
.map((arg) => (typeof arg === "string" ? arg : inspect(arg)))
.map((arg) => formatRuntimeArg(arg))
.join(" ")
.trim();
return {

View File

@@ -1,5 +1,5 @@
import { html, nothing } from "lit";
import { normalizeToolName } from "../../../../src/agents/tool-policy.js";
import { normalizeToolName } from "../../../../src/agents/tool-policy-shared.js";
import type { SkillStatusEntry, SkillStatusReport } from "../types.ts";
import {
isAllowedByPolicy,

View File

@@ -3,7 +3,7 @@ import {
expandToolGroups,
normalizeToolName,
resolveToolProfilePolicy,
} from "../../../../src/agents/tool-policy.js";
} from "../../../../src/agents/tool-policy-shared.js";
import type { AgentIdentityResult, AgentsFilesListResult, AgentsListResult } from "../types.ts";
export const TOOL_SECTIONS = [