mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:50:45 +00:00
fix(diffs): refresh live viewer access policy
This commit is contained in:
@@ -36,6 +36,7 @@ Docs: https://docs.openclaw.ai
|
||||
- CLI/Claude: verify stored Claude CLI session ids have a readable project transcript before resuming, clearing phantom bindings with `reason=transcript-missing` instead of silently starting fresh under `--resume`. Fixes #70177.
|
||||
- CLI sessions: persist CLI session clearing through the atomic session-store merge path, so expired Claude/Codex CLI bindings are actually removed before retrying without the stale session id. (#70298) Thanks @HFConsultant.
|
||||
- ACP/sessions_spawn: honor explicit `model` overrides for ACP child sessions instead of silently falling back to the target agent default model. (#70210) Thanks @felix-miao.
|
||||
- Diffs/viewer: re-read remote viewer access policy from live runtime config on each request, so toggling `plugins.entries.diffs.config.security.allowRemoteViewer` closes proxied viewer access immediately instead of waiting for a restart. Thanks @vincentkoc.
|
||||
- Agents/subagents: drop bare `NO_REPLY` from the parent turn when the session still has pending spawned children, so direct-conversation surfaces such as Telegram DMs no longer rewrite the sentinel into visible fallback chatter while waiting for the child completion event. (#69942) Thanks @neeravmakwana.
|
||||
- Plugins/install: keep bundled plugin dependencies off npm install while repairing them when plugins activate from a packaged install, including Feishu/Lark, Browser, and direct bundled channel setup-entry loads.
|
||||
- Memory/LanceDB: retry initialization after a failed LanceDB load and report unsupported Intel macOS native runtime clearly instead of caching the failure or repeatedly attempting an install that cannot work.
|
||||
|
||||
@@ -192,7 +192,7 @@ describe("PlaywrightDiffScreenshotter", () => {
|
||||
});
|
||||
|
||||
describe("diffs plugin registration", () => {
|
||||
it("applies plugin-config defaults through registered tool and viewer handler", async () => {
|
||||
it("uses live runtime viewer-access config through the registered HTTP handler", async () => {
|
||||
type RegisteredTool = {
|
||||
execute?: (toolCallId: string, params: Record<string, unknown>) => Promise<unknown>;
|
||||
};
|
||||
@@ -207,6 +207,23 @@ describe("diffs plugin registration", () => {
|
||||
| undefined;
|
||||
let registeredHttpRouteHandler: HttpRouteHandler | undefined;
|
||||
const on = vi.fn();
|
||||
let configFile: OpenClawConfig = {
|
||||
gateway: {
|
||||
port: 18789,
|
||||
bind: "loopback",
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
diffs: {
|
||||
config: {
|
||||
security: {
|
||||
allowRemoteViewer: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const api = createTestPluginApi({
|
||||
id: "diffs",
|
||||
@@ -233,7 +250,11 @@ describe("diffs plugin registration", () => {
|
||||
allowRemoteViewer: true,
|
||||
},
|
||||
},
|
||||
runtime: {} as never,
|
||||
runtime: {
|
||||
config: {
|
||||
loadConfig: () => configFile,
|
||||
},
|
||||
} as never,
|
||||
registerTool(tool: Parameters<OpenClawPluginApi["registerTool"]>[0]) {
|
||||
registeredToolFactory = typeof tool === "function" ? tool : () => tool;
|
||||
},
|
||||
@@ -293,6 +314,21 @@ describe("diffs plugin registration", () => {
|
||||
},
|
||||
);
|
||||
|
||||
configFile = {
|
||||
...configFile,
|
||||
plugins: {
|
||||
entries: {
|
||||
diffs: {
|
||||
config: {
|
||||
security: {
|
||||
allowRemoteViewer: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const proxiedRes = createMockServerResponse();
|
||||
const proxiedHandled = await registeredHttpRouteHandler?.(
|
||||
localReq({
|
||||
@@ -306,7 +342,7 @@ describe("diffs plugin registration", () => {
|
||||
);
|
||||
|
||||
expect(proxiedHandled).toBe(true);
|
||||
expect(proxiedRes.statusCode).toBe(200);
|
||||
expect(proxiedRes.statusCode).toBe(404);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ export function createDiffsHttpHandler(params: {
|
||||
allowRemoteViewer?: boolean;
|
||||
trustedProxies?: readonly string[];
|
||||
allowRealIpFallback?: boolean;
|
||||
resolveAccessConfig?: () => {
|
||||
allowRemoteViewer?: boolean;
|
||||
trustedProxies?: readonly string[];
|
||||
allowRealIpFallback?: boolean;
|
||||
};
|
||||
}) {
|
||||
const viewerFailureLimiter = new ViewerFailureLimiter();
|
||||
|
||||
@@ -46,11 +51,16 @@ export function createDiffsHttpHandler(params: {
|
||||
return false;
|
||||
}
|
||||
|
||||
const access = resolveViewerAccess(req, {
|
||||
const accessConfig = params.resolveAccessConfig?.() ?? {
|
||||
allowRemoteViewer: params.allowRemoteViewer,
|
||||
trustedProxies: params.trustedProxies,
|
||||
allowRealIpFallback: params.allowRealIpFallback,
|
||||
};
|
||||
const access = resolveViewerAccess(req, {
|
||||
trustedProxies: accessConfig.trustedProxies,
|
||||
allowRealIpFallback: accessConfig.allowRealIpFallback,
|
||||
});
|
||||
if (!access.localRequest && params.allowRemoteViewer !== true) {
|
||||
if (!access.localRequest && accessConfig.allowRemoteViewer !== true) {
|
||||
respondText(res, 404, "Diff not found");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { resolvePluginConfigObject } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolvePreferredOpenClawTmpDir, type OpenClawPluginApi } from "../api.js";
|
||||
import {
|
||||
resolveDiffsPluginDefaults,
|
||||
@@ -12,12 +13,20 @@ import { createDiffsTool } from "./tool.js";
|
||||
|
||||
export function registerDiffsPlugin(api: OpenClawPluginApi): void {
|
||||
const defaults = resolveDiffsPluginDefaults(api.pluginConfig);
|
||||
const security = resolveDiffsPluginSecurity(api.pluginConfig);
|
||||
const viewerBaseUrl = resolveDiffsPluginViewerBaseUrl(api.pluginConfig);
|
||||
const store = new DiffArtifactStore({
|
||||
rootDir: path.join(resolvePreferredOpenClawTmpDir(), "openclaw-diffs"),
|
||||
logger: api.logger,
|
||||
});
|
||||
const resolveCurrentAccessConfig = () => {
|
||||
const currentConfig = api.runtime.config?.loadConfig?.() ?? api.config;
|
||||
const pluginConfig = resolvePluginConfigObject(currentConfig, "diffs") ?? api.pluginConfig;
|
||||
return {
|
||||
allowRemoteViewer: resolveDiffsPluginSecurity(pluginConfig).allowRemoteViewer,
|
||||
trustedProxies: currentConfig.gateway?.trustedProxies,
|
||||
allowRealIpFallback: currentConfig.gateway?.allowRealIpFallback === true,
|
||||
};
|
||||
};
|
||||
|
||||
api.registerTool(
|
||||
(ctx) => createDiffsTool({ api, store, defaults, viewerBaseUrl, context: ctx }),
|
||||
@@ -32,9 +41,10 @@ export function registerDiffsPlugin(api: OpenClawPluginApi): void {
|
||||
handler: createDiffsHttpHandler({
|
||||
store,
|
||||
logger: api.logger,
|
||||
allowRemoteViewer: security.allowRemoteViewer,
|
||||
allowRemoteViewer: resolveDiffsPluginSecurity(api.pluginConfig).allowRemoteViewer,
|
||||
trustedProxies: api.config.gateway?.trustedProxies,
|
||||
allowRealIpFallback: api.config.gateway?.allowRealIpFallback === true,
|
||||
resolveAccessConfig: resolveCurrentAccessConfig,
|
||||
}),
|
||||
});
|
||||
api.on("before_prompt_build", async () => ({
|
||||
|
||||
@@ -51,6 +51,10 @@ const BUNDLED_LIVE_CONFIG_HOOK_GUARDS = {
|
||||
'resolvePluginConfigObject(api.runtime.config.loadConfig(), "active-memory")',
|
||||
"api.runtime.config.loadConfig()",
|
||||
],
|
||||
"extensions/diffs/src/plugin.ts": [
|
||||
'resolvePluginConfigObject(currentConfig, "diffs")',
|
||||
"api.runtime.config?.loadConfig?.() ?? api.config",
|
||||
],
|
||||
"extensions/memory-core/src/dreaming.ts": [
|
||||
'params.reason === "runtime"',
|
||||
"resolveMemoryCorePluginConfig(startupCfg)",
|
||||
|
||||
Reference in New Issue
Block a user