mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-05 19:32:54 +00:00
fix(agents): return schema lookup misses in-band
Return unknown config.schema.lookup paths as an in-band agent gateway tool result instead of throwing into channel warning surfaces. The direct gateway RPC still reports INVALID_REQUEST, preserving the existing protocol contract, while the agent-facing gateway tool returns schema_path_not_found for exploratory misses. Fixes #88813. Thanks @ksj3421. Reported by @cjalden.
This commit is contained in:
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { GatewayClientRequestError } from "../gateway/client.js";
|
||||
import { testing as restartTesting } from "../infra/restart.js";
|
||||
import { withEnvAsync } from "../test-utils/env.js";
|
||||
import { createGatewayTool } from "./tools/gateway-tool.js";
|
||||
@@ -725,4 +726,29 @@ describe("gateway tool", () => {
|
||||
?.schema;
|
||||
expect(schema?.properties).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns an in-band schema lookup miss for unknown paths", async () => {
|
||||
vi.mocked(callGatewayTool).mockRejectedValueOnce(
|
||||
new GatewayClientRequestError({
|
||||
code: "INVALID_REQUEST",
|
||||
message: "config schema path not found",
|
||||
}),
|
||||
);
|
||||
const tool = requireGatewayTool();
|
||||
|
||||
const result = await tool.execute("call6", {
|
||||
action: "config.schema.lookup",
|
||||
path: "agents.main.authorizedSenders",
|
||||
});
|
||||
|
||||
expect(gatewayCall("config.schema.lookup")[2]).toEqual({
|
||||
path: "agents.main.authorizedSenders",
|
||||
});
|
||||
expect(result.details).toEqual({
|
||||
ok: false,
|
||||
code: "schema_path_not_found",
|
||||
path: "agents.main.authorizedSenders",
|
||||
message: "config schema path not found",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { parseConfigJson5, resolveConfigSnapshotHash } from "../../config/io.js"
|
||||
import { applyMergePatch } from "../../config/merge-patch.js";
|
||||
import { extractDeliveryInfo } from "../../config/sessions.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { GatewayClientRequestError } from "../../gateway/client.js";
|
||||
import {
|
||||
buildRestartSuccessContinuation,
|
||||
formatDoctorNonInteractiveHint,
|
||||
@@ -33,6 +34,7 @@ import { callGatewayTool, readGatewayCallOptions } from "./gateway.js";
|
||||
const log = createSubsystemLogger("gateway-tool");
|
||||
|
||||
const DEFAULT_UPDATE_TIMEOUT_MS = 20 * 60_000;
|
||||
const CONFIG_SCHEMA_PATH_NOT_FOUND_MESSAGE = "config schema path not found";
|
||||
// Per SECURITY.md the model/agent itself is not a trusted principal.
|
||||
// `assertGatewayConfigMutationAllowed` is the explicit model -> operator
|
||||
// trust-boundary control on `config.apply`/`config.patch`, so the runtime tool
|
||||
@@ -114,6 +116,14 @@ function stripConfigWriteResultPayload(result: unknown): unknown {
|
||||
return stripped;
|
||||
}
|
||||
|
||||
function isConfigSchemaPathNotFoundError(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof GatewayClientRequestError &&
|
||||
error.gatewayCode === "INVALID_REQUEST" &&
|
||||
error.message.includes(CONFIG_SCHEMA_PATH_NOT_FOUND_MESSAGE)
|
||||
);
|
||||
}
|
||||
|
||||
function parseGatewayConfigMutationRaw(
|
||||
raw: string,
|
||||
action: "config.apply" | "config.patch",
|
||||
@@ -475,8 +485,20 @@ export function createGatewayTool(opts?: {
|
||||
required: true,
|
||||
label: "path",
|
||||
});
|
||||
const result = await callGatewayTool("config.schema.lookup", gatewayOpts, { path });
|
||||
return jsonResult({ ok: true, result });
|
||||
try {
|
||||
const result = await callGatewayTool("config.schema.lookup", gatewayOpts, { path });
|
||||
return jsonResult({ ok: true, result });
|
||||
} catch (error) {
|
||||
if (isConfigSchemaPathNotFoundError(error)) {
|
||||
return jsonResult({
|
||||
ok: false,
|
||||
code: "schema_path_not_found",
|
||||
path,
|
||||
message: CONFIG_SCHEMA_PATH_NOT_FOUND_MESSAGE,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (action === "config.apply") {
|
||||
const { raw, baseHash, snapshotConfig, sessionKey, note, restartDelayMs } =
|
||||
|
||||
Reference in New Issue
Block a user