fix: support root execution and factory-registered tool lookup

- Replace --dangerously-skip-permissions with --allowedTools whitelist
  to support running Claude Code as root (root blocks the former flag)
- Fix /mcp/execute tool lookup for plugins that register tools via
  factory functions (e.g. padded-cell pcexec) where the global registry
  names array is empty — now falls back to instantiating factories and
  matching by returned tool name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zhi
2026-04-17 12:23:43 +00:00
parent 49af2129ae
commit e73a7ea049
2 changed files with 25 additions and 17 deletions

View File

@@ -98,7 +98,7 @@ export async function* dispatchToClaude(
workspace,
agentId = "",
resumeSessionId,
permissionMode = "bypassPermissions",
permissionMode = "default",
openclawTools,
bridgePort = 18800,
bridgeApiKey = "",
@@ -112,8 +112,7 @@ export async function* dispatchToClaude(
prompt,
"--output-format", "stream-json",
"--verbose",
"--permission-mode", permissionMode,
"--dangerously-skip-permissions",
"--allowedTools", "Bash Edit Write Read Glob Grep WebFetch WebSearch NotebookEdit Monitor TodoWrite mcp__openclaw__*",
];
// --append-system-prompt appends to Claude Code's built-in system prompt rather

View File

@@ -321,21 +321,8 @@ export function createBridgeServer(config: BridgeServerConfig): http.Server {
return;
}
// Find the tool registration by name
const toolReg = pluginRegistry.tools.find((t) => t.names.includes(toolName));
if (!toolReg) {
sendJson(res, 200, { error: `Tool '${toolName}' not registered in OpenClaw plugin registry` });
return;
}
// Build tool execution context.
// config is required by memory tools (resolveMemoryToolContext checks it).
// Read from globalThis where index.ts stores api.config on every registration.
// sessionKey must be in OpenClaw's canonical format "agent:<agentId>:<rest>" so that
// parseAgentSessionKey() can extract the agentId for memory tool context resolution.
// Build tool execution context (needed before tool lookup for factory instantiation).
const liveConfig = (_G["_contractorOpenClawConfig"] ?? null) as Record<string, unknown> | null;
// Construct a canonical session key so memory tools can resolve the agentId from it.
// Format: "agent:<agentId>:direct:bridge"
const canonicalSessionKey = execAgentId ? `agent:${execAgentId}:direct:bridge` : undefined;
const toolCtx = {
config: liveConfig ?? undefined,
@@ -345,6 +332,28 @@ export function createBridgeServer(config: BridgeServerConfig): http.Server {
sessionKey: canonicalSessionKey,
};
// Find tool by name. Some plugins register tools via factory functions without
// declaring names upfront (names array is empty). For those, instantiate the
// factory and match by the returned tool's .name property.
let toolReg = pluginRegistry.tools.find((t) => t.names.includes(toolName));
if (!toolReg) {
for (const candidate of pluginRegistry.tools) {
if (candidate.names.length > 0) continue;
try {
const inst = candidate.factory(toolCtx);
const items = Array.isArray(inst) ? inst : [inst];
if (items.some((t) => (t as { name?: string }).name === toolName)) {
toolReg = candidate;
break;
}
} catch { /* skip */ }
}
}
if (!toolReg) {
sendJson(res, 200, { error: `Tool '${toolName}' not registered in OpenClaw plugin registry` });
return;
}
// Instantiate the tool via its factory
const toolOrTools = toolReg.factory(toolCtx);
const toolInstance = Array.isArray(toolOrTools)