refactor: finish export shadow hazard renames (#121471)

* refactor(gateway): distinguish pending node handlers

* refactor(approvals): distinguish button presentation builder

* refactor(daemon): distinguish service home resolver
This commit is contained in:
Peter Steinberger
2026-08-10 01:01:20 -07:00
committed by GitHub
parent 5b478bb64f
commit bcf342903f
13 changed files with 37 additions and 47 deletions
@@ -11,14 +11,14 @@ c0b60f2e239bc88e8dadbf7b9583c126822678f5d70c880f90f1d447b00e5170 module/agent-r
8fecb210e22bce4532b6ab649b09465f0bd2c857a44abf40db7d683d6491e6da module/allow-from
eba56a699695ffd3bcbf897da0aa93b51294abf1b9542907648b1c30db8c5763 module/allowlist-config-edit
bcb0aa5ac50e9f0c3f72faf18765d36f6e4b5c27082049d8b8aa63c303d37ac7 module/approval-auth-runtime
9624e365c80990675023b34bf46dd2dbc1e9ffc379d478ad800c9c0ef298ada2 module/approval-client-runtime
a598be2363f3fd442c2084ea441ce82e9227ab7b4559d6d18f5f6f5151f6be3c module/approval-delivery-runtime
b7c6bacd60272de8c45cb16c6c75e6acc7eb6580d55f2a3c7543e697b91470f7 module/approval-client-runtime
4fb7f61d33a20570cc79896429b36a40e2c39062a7875e737ed68f262b0bcf38 module/approval-delivery-runtime
0b11bcea0a4b248126d478b50111f922f888750f90a47eb7648d8f19cc36b0a3 module/approval-gateway-runtime
eee50f080f9447135fe72dba2102cf0faf9194d37e5fb07e4a0dc78ac719f77d module/approval-handler-adapter-runtime
2ee0442d19db08d563f61e7d71d5d45776d2a06c4d233317c5171e1a297dcef3 module/approval-handler-runtime
92253e395bb70ec96cde68e7b9aff64316edd148a7eecfa9e7909774e35c9cd6 module/approval-native-runtime
981a13f5c8445e558e17a4d6bb1f476ef0d9e03e0bc0d3c363b422636e6d3277 module/approval-reply-runtime
8e12da9db8ce40d20449de6116c59f800f3f4a452eee2d35b3e8ca4399a5a0b7 module/approval-runtime
886143c449b7d46046f6da65aedd636e8742853250524457464b7f6e8bab949c module/approval-native-runtime
aee9ee8745eba7a1ff464920ecb1807c0b4cab603d0506b42a3647c301cc132d module/approval-reply-runtime
22991b618ee3b322f2f6891b0a82853ff56362425b2bed0713723f6197d403f6 module/approval-runtime
01ca912836b8dec672f705e294f72d346e778557e4c591317d67558ea7669c0b module/archive
d7e53de63b0ac11a266e4abdc18ba6e9401b80309f5c8f5f6a72a00f65dfe3bd module/boolean-param
0d9b23b23425e07595d7457b3b158197244b7ba8615d9fbc358bad13dddb417f module/channel-actions
@@ -76,7 +76,7 @@ dd9f6e0fd33cc88b22543c1ee30cc09cf4de4d8f30dff7b7f9cebef885c21543 module/gateway
f5e190bbfe0c21e76b7281a73cf5e9db806a1ed6e724fac2fb83ade5ccb827a0 module/inbound-envelope
4928af5d2509f696b896f53ac790303a0742202dbcdae3e44fe6d1b434a9c1ba module/inbound-event-delivery
4b85419d23f930c761ad8a13f37fafba0f89a9b9e83ba98b9a3f58b19422f42d module/inbound-reply-dispatch
5c223be031a4670052b7a2203f41eb75118d6331b6c6019a5a97714e256042b6 module/infra-runtime
1e15f71b86e4af797fcbd4322833298a86eee95775970758cf02755b23afb4fd module/infra-runtime
ce73721421f1b903dd04ead4df173582e59ea3e9990248102c448b419cc6d272 module/ingress-effect-once
97742f0953ffc4270763b0d62f24875a0c3ed2ca6d90e96a18c52adc15a20cd0 module/interactive-runtime
408d257ab5cc4b88a22b7e7595039cb8fc524b261c44141b294fbd0100ba62ee module/json-store
@@ -44,14 +44,6 @@
],
"sdk": true
},
{
"name": "buildApprovalPresentation",
"files": [
"src/infra/approval-presentation.ts",
"src/infra/exec-approval-reply.ts"
],
"sdk": true
},
{
"name": "buildBundleMcpToolsFromCatalog",
"files": [
@@ -1320,14 +1312,6 @@
],
"sdk": true
},
{
"name": "resolveHomeDir",
"files": [
"src/daemon/paths.ts",
"src/utils.ts"
],
"sdk": true
},
{
"name": "resolveMarketplaceInstallShortcut",
"files": [
+3 -3
View File
@@ -12,7 +12,7 @@ import {
import { resolveLaunchAgentLabel } from "./launchd-label.js";
import { parseLaunchdPlistLabel } from "./launchd-plist.js";
import { readLaunchDaemonPlistLabel } from "./launchd-system.js";
import { resolveHomeDir } from "./paths.js";
import { resolveDaemonHomeDir } from "./paths.js";
import { execSchtasks } from "./schtasks-exec.js";
import { parseSystemdExecStart } from "./systemd-unit.js";
@@ -495,7 +495,7 @@ export async function findExtraGatewayServices(
if (process.platform === "darwin") {
try {
const home = resolveHomeDir(env);
const home = resolveDaemonHomeDir(env);
const userDir = path.join(home, "Library", "LaunchAgents");
for (const svc of await scanLaunchdDir({
dir: userDir,
@@ -527,7 +527,7 @@ export async function findExtraGatewayServices(
if (process.platform === "linux") {
try {
const home = resolveHomeDir(env);
const home = resolveDaemonHomeDir(env);
const userDir = path.join(home, ".config", "systemd", "user");
for (const svc of await scanSystemdDir({
dir: userDir,
+4 -4
View File
@@ -45,7 +45,7 @@ import {
isSystemLaunchDaemonOwnershipError,
} from "./launchd-system.js";
import { formatLine, toPosixPath, writeFormattedLines } from "./output.js";
import { resolveGatewayStateDir, resolveHomeDir } from "./paths.js";
import { resolveDaemonHomeDir, resolveGatewayStateDir } from "./paths.js";
import { resolveGatewaySupervisorLogPaths } from "./restart-logs.js";
import { parseKeyValueOutput } from "./runtime-parse.js";
import { createGatewayLifecycleMutationReporter } from "./service-mutation.js";
@@ -167,7 +167,7 @@ function resolveLaunchAgentPlistPathForLabel(
env: Record<string, string | undefined>,
label: string,
): string {
const home = toPosixPath(resolveHomeDir(env));
const home = toPosixPath(resolveDaemonHomeDir(env));
return path.posix.join(home, "Library", "LaunchAgents", `${label}.plist`);
}
@@ -1025,7 +1025,7 @@ export async function uninstallLaunchAgent({
return;
}
const home = toPosixPath(resolveHomeDir(env));
const home = toPosixPath(resolveDaemonHomeDir(env));
const trashDir = path.posix.join(home, ".Trash");
const dest = path.join(trashDir, `${label}.plist`);
try {
@@ -1338,7 +1338,7 @@ async function writeLaunchAgentPlist({
await ensureSecureDirectory(logDir);
const plistPath = resolveLaunchAgentPlistPathForLabel(env, label);
const home = toPosixPath(resolveHomeDir(env));
const home = toPosixPath(resolveDaemonHomeDir(env));
const libraryDir = path.posix.join(home, "Library");
await ensureSecureDirectory(home);
await ensureSecureDirectory(libraryDir);
+4 -3
View File
@@ -7,7 +7,8 @@ const windowsAbsolutePath = /^[a-zA-Z]:[\\/]/;
const windowsUncPath = /^\\\\/;
/** Resolves the home directory used for daemon state paths. */
export function resolveHomeDir(env: Record<string, string | undefined>): string {
// Daemon unit files must not use infra/home-dir because runtime overrides cannot leak into services.
export function resolveDaemonHomeDir(env: Record<string, string | undefined>): string {
const home = normalizeOptionalString(env.HOME) || normalizeOptionalString(env.USERPROFILE);
if (!home) {
throw new Error("Missing HOME");
@@ -38,10 +39,10 @@ function resolveUserPathWithHome(input: string, home?: string): string {
export function resolveGatewayStateDir(env: Record<string, string | undefined>): string {
const override = normalizeOptionalString(env.OPENCLAW_STATE_DIR);
if (override) {
const home = override.startsWith("~") ? resolveHomeDir(env) : undefined;
const home = override.startsWith("~") ? resolveDaemonHomeDir(env) : undefined;
return resolveUserPathWithHome(override, home);
}
const home = resolveHomeDir(env);
const home = resolveDaemonHomeDir(env);
const suffix = resolveGatewayProfileSuffix(env.OPENCLAW_PROFILE);
// Profile suffixes isolate managed service files while preserving the default
// historical ~/.openclaw state path.
+2 -2
View File
@@ -3,7 +3,7 @@ import fs from "node:fs";
import path from "node:path";
import { quoteCmdScriptArg } from "./cmd-argv.js";
import { resolveGatewayProfileSuffix } from "./constants.js";
import { resolveGatewayStateDir, resolveHomeDir } from "./paths.js";
import { resolveDaemonHomeDir, resolveGatewayStateDir } from "./paths.js";
import type { GatewayLifecycleMutationMode, GatewayServiceEnv } from "./service-types.js";
const GATEWAY_RESTART_LOG_FILENAME = "gateway-restart.log";
@@ -47,7 +47,7 @@ export function resolveGatewayLogPaths(env: GatewayServiceEnv): GatewayLogPaths
}
function resolveMacLaunchAgentLogPaths(env: GatewayServiceEnv): GatewayLogPaths {
const home = resolveHomeDir(env).replaceAll("\\", "/");
const home = resolveDaemonHomeDir(env).replaceAll("\\", "/");
const logDir = path.posix.join(home, "Library", "Logs", "openclaw");
const prefix = resolveMacLaunchAgentLogPrefix(env);
return {
+3 -3
View File
@@ -26,7 +26,7 @@ import {
} from "./constants.js";
import { execFileUtf8 } from "./exec-file.js";
import { formatLine, toPosixPath, writeFormattedLines } from "./output.js";
import { resolveHomeDir } from "./paths.js";
import { resolveDaemonHomeDir } from "./paths.js";
import { parseKeyValueOutput } from "./runtime-parse.js";
import {
hasEnvironmentFileSource,
@@ -68,7 +68,7 @@ const SYSTEMD_GATEWAY_DOTENV_FILENAME = "gateway.systemd.env";
const SYSTEMD_NODE_DOTENV_FILENAME = "node.systemd.env";
function resolveSystemdUnitPathForName(env: GatewayServiceEnv, name: string): string {
const home = toPosixPath(resolveHomeDir(env));
const home = toPosixPath(resolveDaemonHomeDir(env));
return path.posix.join(home, ".config", "systemd", "user", `${name}.service`);
}
@@ -523,7 +523,7 @@ async function assertNoSystemGatewayOwnership(env: GatewayServiceEnv): Promise<v
function expandSystemdSpecifier(input: string, env: GatewayServiceEnv): string {
// Support the common unit-specifier used in user services.
return input.replaceAll("%h", toPosixPath(resolveHomeDir(env)));
return input.replaceAll("%h", toPosixPath(resolveDaemonHomeDir(env)));
}
function parseEnvironmentFileSpecs(raw: string): string[] {
@@ -39,7 +39,7 @@ vi.mock("../node-wake-state.js", () => ({
releaseNodeWakeLifecycle: mocks.releaseNodeWakeLifecycle,
}));
vi.mock("./nodes.js", () => ({
vi.mock("./nodes.wake.js", () => ({
maybeWakeNodeWithApns: mocks.maybeWakeNodeWithApns,
maybeSendNodeWakeNudge: mocks.maybeSendNodeWakeNudge,
waitForNodeReconnect: mocks.waitForNodeReconnect,
@@ -26,7 +26,11 @@ import {
releaseNodeWakeLifecycle,
} from "../node-wake-state.js";
import { respondInvalidParams, respondUnavailableOnThrow } from "./nodes.helpers.js";
import { maybeSendNodeWakeNudge, maybeWakeNodeWithApns, waitForNodeReconnect } from "./nodes.js";
import {
maybeSendNodeWakeNudge,
maybeWakeNodeWithApns,
waitForNodeReconnect,
} from "./nodes.wake.js";
import type { RespondFn } from "./shared-types.js";
import type { GatewayRequestHandlers } from "./types.js";
+2 -2
View File
@@ -38,7 +38,7 @@ vi.mock("./exec-approval-surface.js", () => ({
}));
import {
buildApprovalPresentation,
buildApprovalButtonPresentation,
buildApprovalPresentationFromActionDescriptors,
buildExecApprovalActionDescriptors,
buildExecApprovalCommandText,
@@ -508,7 +508,7 @@ describe("exec approval reply helpers", () => {
]);
expect(
buildApprovalPresentation({
buildApprovalButtonPresentation({
approvalId: "req-1",
allowedDecisions: ["deny"],
}),
+3 -3
View File
@@ -258,7 +258,7 @@ type BuildApprovalPresentationParams = {
};
/** Build the shipped command-backed portable approval controls. */
export function buildApprovalPresentation(
export function buildApprovalButtonPresentation(
params: BuildApprovalPresentationParams,
): MessagePresentation | undefined {
return buildApprovalPresentationFromActionDescriptors(
@@ -290,7 +290,7 @@ export function buildExecApprovalPresentation(params: {
ask?: string | null;
allowedDecisions?: readonly ExecApprovalReplyDecision[];
}): MessagePresentation | undefined {
return buildApprovalPresentation({
return buildApprovalButtonPresentation({
approvalId: params.approvalCommandId,
ask: params.ask,
allowedDecisions: params.allowedDecisions,
@@ -440,7 +440,7 @@ export function buildExecApprovalPendingReplyPayload(
return {
text: lines.join("\n\n"),
presentation: buildApprovalPresentation({
presentation: buildApprovalButtonPresentation({
approvalId: params.approvalId,
allowedDecisions,
}),
+2 -2
View File
@@ -1,7 +1,7 @@
// Approval renderer helpers convert approval request data into channel-safe display text.
import { normalizeOptionalString } from "../../packages/normalization-core/src/string-coerce.js";
import {
buildApprovalPresentation,
buildApprovalButtonPresentation,
buildTypedApprovalPresentation,
type ExecApprovalReplyDecision,
} from "../infra/exec-approval-reply.js";
@@ -43,7 +43,7 @@ export function buildApprovalPendingReplyPayload(
const allowedDecisions = params.allowedDecisions ?? DEFAULT_ALLOWED_DECISIONS;
return {
text: params.text,
presentation: buildApprovalPresentation({
presentation: buildApprovalButtonPresentation({
approvalId: params.approvalId,
allowedDecisions,
}),
+2 -1
View File
@@ -2,7 +2,8 @@
* Runtime SDK subpath for building approval replies and exec approval presentations.
*/
export {
buildApprovalPresentation,
// Shipped Plugin SDK compatibility alias; remove in the next major release.
buildApprovalButtonPresentation as buildApprovalPresentation,
buildApprovalPresentationFromActionDescriptors,
buildExecApprovalPresentation,
buildExecApprovalActionDescriptors,