Skip to content

Commit 121cd05

Browse files
committed
fix: reuse plugin metadata in local agent turns
1 parent c90e42a commit 121cd05

2 files changed

Lines changed: 59 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Docs: https://docs.openclaw.ai
6464
- Gateway/exec approvals: wait for accepted async approval follow-up runs instead of direct-fallback sending duplicate completions when retries use different nonce keys. Fixes #82711. (#82717) Thanks @udaymanish6.
6565
- Agents/subagents: mark completed subagent handoffs as ready for parent review so requester agents verify results and continue required follow-up work before reporting done. (#82724) Thanks @100menotu001.
6666
- QA-Lab: validate Capture saved views loaded from browser storage so malformed local state cannot poison Capture inspector filters or layout controls. (#77722) Thanks @AsaZhou923.
67+
- Agents/performance: reuse prepared plugin manifest metadata across local CLI turns, model catalog normalization, auth lookups, and tool capability checks, restoring fast pre-provider startup for plugin-heavy installs. Thanks @shakkernerd.
6768
- CLI/config: add `--dry-run` support to `openclaw config unset`, with `--json` output and allow-exec validation parity with `config set`/`config patch` dry-run handling. (#81895) Thanks @giodl73-repo.
6869
- Memory-core: retry disabled dreaming cron cleanup until cron is available after startup, so persisted managed dreaming jobs are removed after restart. Fixes #82383. (#82389) Thanks @neeravmakwana.
6970
- Providers/xAI: keep retired Grok 3, Grok 4 Fast, Grok 4.1 Fast, and Grok Code slugs out of model pickers while preserving compatibility resolution for existing configs.

src/agents/agent-command.ts

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {
2020
import { formatErrorMessage } from "../infra/errors.js";
2121
import { buildOutboundSessionContext } from "../infra/outbound/session-context.js";
2222
import { createSubsystemLogger } from "../logging/subsystem.js";
23+
import { setCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
24+
import { loadManifestMetadataSnapshot } from "../plugins/manifest-contract-eligibility.js";
2325
import {
2426
isSubagentSessionKey,
2527
normalizeAgentId,
@@ -36,6 +38,7 @@ import { createLazyImportLoader } from "../shared/lazy-promise.js";
3638
import { normalizeOptionalString } from "../shared/string-coerce.js";
3739
import { sanitizeForLog } from "../terminal/ansi.js";
3840
import { createTrajectoryRuntimeRecorder } from "../trajectory/runtime.js";
41+
import { resolveUserPath } from "../utils.js";
3942
import { resolveMessageChannel } from "../utils/message-channel.js";
4043
import { resolveAgentRuntimeConfig } from "./agent-runtime-config.js";
4144
import {
@@ -339,27 +342,6 @@ async function prepareAgentCommandExecution(
339342
}
340343
}
341344
const agentCfg = cfg.agents?.defaults;
342-
const configuredModel = resolveConfiguredModelRef({
343-
cfg,
344-
defaultProvider: DEFAULT_PROVIDER,
345-
defaultModel: DEFAULT_MODEL,
346-
});
347-
const configuredThinkingCatalog = buildConfiguredModelCatalog({ cfg });
348-
const thinkingLevelsHint = formatThinkingLevels(
349-
configuredModel.provider,
350-
configuredModel.model,
351-
", ",
352-
configuredThinkingCatalog.length > 0 ? configuredThinkingCatalog : undefined,
353-
);
354-
355-
const thinkOverride = normalizeThinkLevel(opts.thinking);
356-
const thinkOnce = normalizeThinkLevel(opts.thinkingOnce);
357-
if (opts.thinking && !thinkOverride) {
358-
throw new Error(`Invalid thinking level. Use one of: ${thinkingLevelsHint}.`);
359-
}
360-
if (opts.thinkingOnce && !thinkOnce) {
361-
throw new Error(`Invalid one-shot thinking level. Use one of: ${thinkingLevelsHint}.`);
362-
}
363345

364346
const verboseOverride = normalizeVerboseLevel(opts.verbose);
365347
if (opts.verbose && !verboseOverride) {
@@ -414,13 +396,49 @@ async function prepareAgentCommandExecution(
414396
// Internal callers (for example subagent spawns) may pin workspace inheritance.
415397
const workspaceDirRaw =
416398
normalizedSpawned.workspaceDir ?? resolveAgentWorkspaceDir(cfg, sessionAgentId);
399+
const workspaceDir = resolveUserPath(workspaceDirRaw);
417400
const agentDir = resolveAgentDir(cfg, sessionAgentId);
418-
const workspace = await ensureAgentWorkspace({
401+
const manifestMetadataSnapshot = loadManifestMetadataSnapshot({
402+
config: cfg,
403+
workspaceDir,
404+
env: process.env,
405+
});
406+
setCurrentPluginMetadataSnapshot(manifestMetadataSnapshot, {
407+
config: cfg,
408+
env: process.env,
409+
workspaceDir,
410+
});
411+
const manifestPlugins = manifestMetadataSnapshot.plugins;
412+
const configuredModel = resolveConfiguredModelRef({
413+
cfg,
414+
defaultProvider: DEFAULT_PROVIDER,
415+
defaultModel: DEFAULT_MODEL,
416+
manifestPlugins,
417+
});
418+
const configuredThinkingCatalog = buildConfiguredModelCatalog({
419+
cfg,
420+
workspaceDir,
421+
manifestPlugins,
422+
});
423+
const thinkingLevelsHint = formatThinkingLevels(
424+
configuredModel.provider,
425+
configuredModel.model,
426+
", ",
427+
configuredThinkingCatalog.length > 0 ? configuredThinkingCatalog : undefined,
428+
);
429+
const thinkOverride = normalizeThinkLevel(opts.thinking);
430+
const thinkOnce = normalizeThinkLevel(opts.thinkingOnce);
431+
if (opts.thinking && !thinkOverride) {
432+
throw new Error(`Invalid thinking level. Use one of: ${thinkingLevelsHint}.`);
433+
}
434+
if (opts.thinkingOnce && !thinkOnce) {
435+
throw new Error(`Invalid one-shot thinking level. Use one of: ${thinkingLevelsHint}.`);
436+
}
437+
await ensureAgentWorkspace({
419438
dir: workspaceDirRaw,
420439
ensureBootstrapFiles: !agentCfg?.skipBootstrap,
421440
skipOptionalBootstrapFiles: agentCfg?.skipOptionalBootstrapFiles,
422441
});
423-
const workspaceDir = workspace.dir;
424442
const runId = opts.runId?.trim() || sessionId;
425443
const { getAcpSessionManager } = await loadAcpManagerRuntime();
426444
const acpManager = getAcpSessionManager();
@@ -460,6 +478,7 @@ async function prepareAgentCommandExecution(
460478
outboundSession,
461479
workspaceDir,
462480
agentDir,
481+
manifestPlugins,
463482
runId,
464483
acpManager,
465484
acpResolution,
@@ -499,6 +518,7 @@ async function agentCommandInternal(
499518
runId,
500519
acpManager,
501520
acpResolution,
521+
manifestPlugins,
502522
} = prepared;
503523
let sessionEntry = prepared.sessionEntry;
504524

@@ -750,10 +770,12 @@ async function agentCommandInternal(
750770
const configuredDefaultRef = resolveDefaultModelForAgent({
751771
cfg,
752772
agentId: sessionAgentId,
773+
manifestPlugins,
753774
});
754775
const { provider: defaultProvider, model: defaultModel } = normalizeModelRef(
755776
configuredDefaultRef.provider,
756777
configuredDefaultRef.model,
778+
{ manifestPlugins },
757779
);
758780
let provider = defaultProvider;
759781
let model = defaultModel;
@@ -786,6 +808,7 @@ async function agentCommandInternal(
786808
catalog: [],
787809
defaultProvider,
788810
defaultModel,
811+
manifestPlugins,
789812
});
790813

791814
if (needsModelCatalog) {
@@ -796,6 +819,7 @@ async function agentCommandInternal(
796819
defaultProvider,
797820
defaultModel,
798821
agentId: sessionAgentId,
822+
manifestPlugins,
799823
});
800824
allowedModelCatalog = visibilityPolicy.allowedCatalog;
801825
}
@@ -818,7 +842,9 @@ async function agentCommandInternal(
818842
const overrideProvider = sessionEntry.providerOverride?.trim() || defaultProvider;
819843
const overrideModel = sessionEntry.modelOverride?.trim();
820844
if (overrideModel) {
821-
const normalizedOverride = normalizeModelRef(overrideProvider, overrideModel);
845+
const normalizedOverride = normalizeModelRef(overrideProvider, overrideModel, {
846+
manifestPlugins,
847+
});
822848
const key = modelKey(normalizedOverride.provider, normalizedOverride.model);
823849
if (!visibilityPolicy.allowsKey(key)) {
824850
const { updated } = applyModelOverrideToSessionEntry({
@@ -841,7 +867,9 @@ async function agentCommandInternal(
841867
let storedModelOverride = sessionEntry?.modelOverride?.trim();
842868
if (storedModelOverride) {
843869
const candidateProvider = storedProviderOverride || defaultProvider;
844-
const normalizedStored = normalizeModelRef(candidateProvider, storedModelOverride);
870+
const normalizedStored = normalizeModelRef(candidateProvider, storedModelOverride, {
871+
manifestPlugins,
872+
});
845873
const key = modelKey(normalizedStored.provider, normalizedStored.model);
846874
if (visibilityPolicy.allowsKey(key)) {
847875
provider = normalizedStored.provider;
@@ -867,10 +895,10 @@ async function agentCommandInternal(
867895
if (hasExplicitRunOverride) {
868896
const explicitRef = explicitModelOverride
869897
? explicitProviderOverride
870-
? normalizeModelRef(explicitProviderOverride, explicitModelOverride)
871-
: parseModelRef(explicitModelOverride, provider)
898+
? normalizeModelRef(explicitProviderOverride, explicitModelOverride, { manifestPlugins })
899+
: parseModelRef(explicitModelOverride, provider, { manifestPlugins })
872900
: explicitProviderOverride
873-
? normalizeModelRef(explicitProviderOverride, model)
901+
? normalizeModelRef(explicitProviderOverride, model, { manifestPlugins })
874902
: null;
875903
if (!explicitRef) {
876904
throw new Error("Invalid model override.");
@@ -1085,6 +1113,7 @@ async function agentCommandInternal(
10851113
cfg,
10861114
provider,
10871115
model,
1116+
manifestPlugins,
10881117
runId,
10891118
agentDir,
10901119
fallbacksOverride: effectiveFallbacksOverride,
@@ -1276,7 +1305,7 @@ async function agentCommandInternal(
12761305
{ cause: err },
12771306
);
12781307
}
1279-
const switchRef = normalizeModelRef(err.provider, err.model);
1308+
const switchRef = normalizeModelRef(err.provider, err.model, { manifestPlugins });
12801309
const switchKey = modelKey(switchRef.provider, switchRef.model);
12811310
if (!visibilityPolicy.allowsKey(switchKey)) {
12821311
log.info(

0 commit comments

Comments
 (0)