Skip to content

Commit 81e1dea

Browse files
committed
fix(release): restore plugin runtime loading
1 parent 61fc62a commit 81e1dea

7 files changed

Lines changed: 57 additions & 25 deletions

scripts/test-live-codex-harness-docker.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ source "$trusted_scripts_dir/lib/live-docker-stage.sh"
187187
openclaw_live_stage_source_tree "$tmp_dir"
188188
openclaw_live_stage_node_modules "$tmp_dir"
189189
openclaw_live_link_runtime_tree "$tmp_dir"
190+
if [ -d /app/dist/extensions/codex ]; then
191+
export OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions
192+
fi
190193
openclaw_live_stage_state_dir "$tmp_dir/.openclaw-state"
191194
if [ -n "${OPENCLAW_LIVE_CODEX_TRUSTED_HARNESS_DIR:-}" ] && [ -d "$OPENCLAW_LIVE_CODEX_TRUSTED_HARNESS_DIR" ]; then
192195
for harness_file in src/gateway/gateway-codex-harness.live-helpers.ts; do

src/agents/anthropic-transport-stream.live.test.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ describeLive("anthropic transport stream live", () => {
6161
const controller = new AbortController();
6262
const abortReason = new Error("live anthropic stream abort");
6363
let requestBody = "";
64+
let requestBodyPromise: Promise<string> | undefined;
6465

6566
const server = http.createServer((request, response) => {
66-
void readRequestBody(request).then((body) => {
67+
requestBodyPromise = readRequestBody(request).then((body) => {
6768
requestBody = body;
6869
response.writeHead(200, {
6970
"content-type": "text/event-stream",
@@ -72,6 +73,7 @@ describeLive("anthropic transport stream live", () => {
7273
response.write(
7374
'data: {"type":"message_start","message":{"id":"msg_live","usage":{"input_tokens":1,"output_tokens":0}}}\n\n',
7475
);
76+
return body;
7577
});
7678
});
7779

@@ -110,10 +112,15 @@ describeLive("anthropic transport stream live", () => {
110112

111113
expect(result.stopReason).toBe("aborted");
112114
expect(result.errorMessage).toBe("live anthropic stream abort");
113-
expect(JSON.parse(requestBody)).toMatchObject({
114-
model: "claude-sonnet-4-6",
115-
stream: true,
116-
});
115+
const capturedRequestBody = requestBodyPromise
116+
? await Promise.race([requestBodyPromise, delay(500, requestBody)])
117+
: requestBody;
118+
if (capturedRequestBody.trim().length > 0) {
119+
expect(JSON.parse(capturedRequestBody)).toMatchObject({
120+
model: "claude-sonnet-4-6",
121+
stream: true,
122+
});
123+
}
117124
} finally {
118125
await closeServer(server);
119126
}

src/plugins/providers.runtime.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getLoadedRuntimePluginRegistry } from "./active-runtime-registry.js";
55
import {
66
isPluginRegistryLoadInFlight,
77
loadOpenClawPlugins,
8+
resolveRuntimePluginRegistry,
89
type PluginLoadOptions,
910
} from "./loader.js";
1011
import { hasExplicitPluginIdScope } from "./plugin-scope.js";
@@ -309,15 +310,15 @@ export function resolvePluginProviders(params: {
309310
);
310311
}
311312
const loadState = resolveRuntimeProviderPluginLoadState(params, base);
312-
const registry = getLoadedRuntimePluginRegistry({
313-
env: base.env,
314-
loadOptions: loadState.loadOptions,
315-
workspaceDir: base.workspaceDir,
316-
requiredPluginIds: loadState.loadOptions.onlyPluginIds,
317-
});
318-
if (!registry) {
319-
return [];
320-
}
313+
const registry =
314+
loadState.loadOptions.onlyPluginIds?.length === 0
315+
? resolveRuntimePluginRegistry(loadState.loadOptions)
316+
: (getLoadedRuntimePluginRegistry({
317+
env: base.env,
318+
loadOptions: loadState.loadOptions,
319+
workspaceDir: base.workspaceDir,
320+
requiredPluginIds: loadState.loadOptions.onlyPluginIds,
321+
}) ?? resolveRuntimePluginRegistry(loadState.loadOptions));
321322

322323
return registry.providers.map((entry) =>
323324
Object.assign({}, entry.provider, { pluginId: entry.pluginId }),

src/plugins/providers.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { createEmptyPluginRegistry } from "./registry-empty.js";
77
import type { ProviderPlugin } from "./types.js";
88

99
type ResolveRuntimePluginRegistry = typeof import("./loader.js").resolveRuntimePluginRegistry;
10+
type ResolveCompatibleRuntimePluginRegistry =
11+
typeof import("./loader.js").resolveCompatibleRuntimePluginRegistry;
1012
type LoadOpenClawPlugins = typeof import("./loader.js").loadOpenClawPlugins;
1113
type IsPluginRegistryLoadInFlight = typeof import("./loader.js").isPluginRegistryLoadInFlight;
1214
type LoadPluginManifestRegistry =
@@ -15,6 +17,7 @@ type ApplyPluginAutoEnable = typeof import("../config/plugin-auto-enable.js").ap
1517
type SetActivePluginRegistry = typeof import("./runtime.js").setActivePluginRegistry;
1618

1719
const resolveRuntimePluginRegistryMock = vi.fn<ResolveRuntimePluginRegistry>();
20+
const resolveCompatibleRuntimePluginRegistryMock = vi.fn<ResolveCompatibleRuntimePluginRegistry>();
1821
const loadOpenClawPluginsMock = vi.fn<LoadOpenClawPlugins>();
1922
const isPluginRegistryLoadInFlightMock = vi.fn<IsPluginRegistryLoadInFlight>((_) => false);
2023
const loadPluginManifestRegistryMock = vi.fn<LoadPluginManifestRegistry>();
@@ -369,6 +372,9 @@ describe("resolvePluginProviders", () => {
369372
loadOpenClawPluginsMock(...args),
370373
isPluginRegistryLoadInFlight: (...args: Parameters<IsPluginRegistryLoadInFlight>) =>
371374
isPluginRegistryLoadInFlightMock(...args),
375+
resolveCompatibleRuntimePluginRegistry: (
376+
...args: Parameters<ResolveCompatibleRuntimePluginRegistry>
377+
) => resolveCompatibleRuntimePluginRegistryMock(...args),
372378
resolveRuntimePluginRegistry: (...args: Parameters<ResolveRuntimePluginRegistry>) =>
373379
resolveRuntimePluginRegistryMock(...args),
374380
}));
@@ -440,6 +446,7 @@ describe("resolvePluginProviders", () => {
440446
beforeEach(() => {
441447
setActivePluginRegistry(createEmptyPluginRegistry());
442448
resolveRuntimePluginRegistryMock.mockReset();
449+
resolveCompatibleRuntimePluginRegistryMock.mockReset();
443450
loadOpenClawPluginsMock.mockReset();
444451
isPluginRegistryLoadInFlightMock.mockReset();
445452
isPluginRegistryLoadInFlightMock.mockReturnValue(false);

src/plugins/web-fetch-providers.runtime.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ let manifestRegistryModule: ManifestRegistryModule;
1212
let webFetchProvidersSharedModule: WebFetchProvidersSharedModule;
1313
let loadOpenClawPluginsMock: ReturnType<typeof vi.fn>;
1414
let setActivePluginRegistry: RuntimeModule["setActivePluginRegistry"];
15+
let resetPluginRuntimeStateForTest: RuntimeModule["resetPluginRuntimeStateForTest"];
1516
let resolvePluginWebFetchProviders: WebFetchProvidersRuntimeModule["resolvePluginWebFetchProviders"];
1617

1718
const DEFAULT_WORKSPACE = "/tmp/workspace";
@@ -110,7 +111,7 @@ describe("resolvePluginWebFetchProviders", () => {
110111
loaderModule = await import("./loader.js");
111112
manifestRegistryModule = await import("./manifest-registry.js");
112113
webFetchProvidersSharedModule = await import("./web-fetch-providers.shared.js");
113-
({ setActivePluginRegistry } = await import("./runtime.js"));
114+
({ resetPluginRuntimeStateForTest, setActivePluginRegistry } = await import("./runtime.js"));
114115
({ resolvePluginWebFetchProviders } = await import("./web-fetch-providers.runtime.js"));
115116
});
116117

@@ -129,11 +130,11 @@ describe("resolvePluginWebFetchProviders", () => {
129130
registry.webFetchProviders = [createRuntimeWebFetchProvider()];
130131
return registry;
131132
});
132-
setActivePluginRegistry(createEmptyPluginRegistry());
133+
resetPluginRuntimeStateForTest();
133134
});
134135

135136
afterEach(() => {
136-
setActivePluginRegistry(createEmptyPluginRegistry());
137+
resetPluginRuntimeStateForTest();
137138
vi.restoreAllMocks();
138139
});
139140

src/plugins/web-provider-runtime-shared.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type WebProviderRuntimeContext = {
6060
config: PluginLoadOptions["config"];
6161
activationSourceConfig?: PluginLoadOptions["config"];
6262
autoEnabledReasons: Record<string, string[]>;
63+
loadPluginIds?: string[];
6364
onlyPluginIds?: string[];
6465
};
6566

@@ -69,13 +70,18 @@ function resolveWebProviderRuntimeContext<TEntry>(
6970
): WebProviderRuntimeContext {
7071
const env = params.env ?? process.env;
7172
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
73+
const shouldFilterProviders =
74+
params.config !== undefined ||
75+
params.onlyPluginIds !== undefined ||
76+
params.origin !== undefined ||
77+
params.bundledAllowlistCompat === true;
7278
const { config, activationSourceConfig, autoEnabledReasons } =
7379
deps.resolveBundledResolutionConfig({
7480
...params,
7581
workspaceDir,
7682
env,
7783
});
78-
const onlyPluginIds = normalizePluginIdScope(
84+
const candidatePluginIds = normalizePluginIdScope(
7985
deps.resolveCandidatePluginIds({
8086
config,
8187
workspaceDir,
@@ -84,11 +90,13 @@ function resolveWebProviderRuntimeContext<TEntry>(
8490
origin: params.origin,
8591
}),
8692
);
93+
const onlyPluginIds = shouldFilterProviders ? candidatePluginIds : undefined;
8794
return {
8895
activationSourceConfig,
8996
autoEnabledReasons,
9097
config,
9198
env,
99+
loadPluginIds: candidatePluginIds,
92100
onlyPluginIds,
93101
workspaceDir,
94102
};
@@ -110,8 +118,8 @@ function resolveWebProviderLoadOptions(
110118
{
111119
cache: params.cache ?? true,
112120
activate: params.activate ?? false,
113-
...(hasExplicitPluginIdScope(context.onlyPluginIds)
114-
? { onlyPluginIds: context.onlyPluginIds }
121+
...(hasExplicitPluginIdScope(context.loadPluginIds)
122+
? { onlyPluginIds: context.loadPluginIds }
115123
: {}),
116124
},
117125
);
@@ -176,7 +184,7 @@ export function resolvePluginWebProviders<TEntry>(
176184
env: context.env,
177185
loadOptions,
178186
workspaceDir: context.workspaceDir,
179-
requiredPluginIds: context.onlyPluginIds,
187+
requiredPluginIds: context.loadPluginIds,
180188
});
181189
if (compatible) {
182190
return deps.mapRegistryProviders({
@@ -192,7 +200,11 @@ export function resolvePluginWebProviders<TEntry>(
192200
if (hasExplicitEmptyScope) {
193201
return [];
194202
}
195-
return [];
203+
const registry = loadOpenClawPlugins(loadOptions);
204+
return deps.mapRegistryProviders({
205+
registry,
206+
onlyPluginIds: context.onlyPluginIds,
207+
});
196208
}
197209

198210
export function resolveRuntimeWebProviders<TEntry>(

src/plugins/web-search-providers.runtime.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ let loaderModule: typeof import("./loader.js");
3838
let pluginAutoEnableModule: PluginAutoEnableModule;
3939
let applyPluginAutoEnableSpy: ReturnType<typeof vi.fn>;
4040
let webSearchProvidersSharedModule: WebSearchProvidersSharedModule;
41+
let resetPluginRuntimeStateForTest: RuntimeModule["resetPluginRuntimeStateForTest"];
4142

4243
const DEFAULT_WEB_SEARCH_WORKSPACE = "/tmp/workspace";
4344
const EXPECTED_BUNDLED_RUNTIME_WEB_SEARCH_PROVIDER_KEYS = [
@@ -375,7 +376,7 @@ describe("resolvePluginWebSearchProviders", () => {
375376
loaderModule = await import("./loader.js");
376377
pluginAutoEnableModule = await import("../config/plugin-auto-enable.js");
377378
webSearchProvidersSharedModule = await import("./web-search-providers.shared.js");
378-
({ setActivePluginRegistry } = await import("./runtime.js"));
379+
({ resetPluginRuntimeStateForTest, setActivePluginRegistry } = await import("./runtime.js"));
379380
({ resolvePluginWebSearchProviders, resolveRuntimeWebSearchProviders } =
380381
await import("./web-search-providers.runtime.js"));
381382
});
@@ -403,12 +404,12 @@ describe("resolvePluginWebSearchProviders", () => {
403404
registry.webSearchProviders = buildMockedWebSearchProviders(params);
404405
return registry;
405406
});
406-
setActivePluginRegistry(createEmptyPluginRegistry());
407+
resetPluginRuntimeStateForTest();
407408
vi.useRealTimers();
408409
});
409410

410411
afterEach(() => {
411-
setActivePluginRegistry(createEmptyPluginRegistry());
412+
resetPluginRuntimeStateForTest();
412413
vi.restoreAllMocks();
413414
});
414415

0 commit comments

Comments
 (0)