mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:40:49 +00:00
fix(agents): preserve workspace metadata reuse
Pass the resolved agent workspace through hot model refresh paths so workspace-scoped plugin metadata snapshots can be reused. Refs #77519. Refs #77532.
This commit is contained in:
committed by
GitHub
parent
343f859b90
commit
a7263de258
@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Changes
|
||||
|
||||
- Dependencies: refresh runtime and provider packages including Pi 0.73.0, ACPX adapters, OpenAI, Anthropic, Slack, and TypeScript native preview, while keeping the Bedrock runtime installer override pinned below the Windows ARM Node 24 npm resolver failure.
|
||||
- Agents/performance: pass the resolved workspace through BTW, compaction, embedded-run model generation, and PDF model setup so explicit agent-dir model refreshes can reuse the current workspace-scoped plugin metadata snapshot instead of falling back to cold plugin metadata scans. (#77519, #77532)
|
||||
- Plugins/active-memory: skip session-store channel entries that contain `:` when resolving the recall subagent's channel, so QQ c2c agent IDs (e.g. `c2c:10D4F7C2…`) and other scoped conversation IDs do not reach bundled-plugin `dirName` validation and crash the recall run. The same guard already applied to explicit `channelId` params (#76704); this extends it to store-derived channels. (#77396) Thanks @hclsys.
|
||||
- Secrets/external channel contracts: also look in `<rootDir>/dist/` when resolving the `secret-contract-api` sidecar, so npm-published externalized channel plugins (e.g. `@openclaw/discord` since 2026.5.2) whose compiled artifacts live under `dist/` actually contribute their channel SecretRef contracts to the runtime snapshot. Without this, env-backed `channels.discord.token` SecretRefs silently failed to resolve at gateway start on 2026.5.3, leaving the channel `not configured` even though #76449 had landed the generic external-contract loader. Thanks @mogglemoss.
|
||||
- Models/auth: add `openclaw models auth list [--provider <id>] [--json]` so users can inspect saved per-agent auth profiles without dumping secrets or hitting the old “too many arguments” path. Thanks @vincentkoc.
|
||||
|
||||
@@ -417,6 +417,13 @@ describe("runBtwSideQuestion", () => {
|
||||
const result = await runSideQuestion();
|
||||
|
||||
expect(result).toEqual({ text: "Final answer." });
|
||||
expect(ensureOpenClawModelsJsonMock).toHaveBeenCalledWith(
|
||||
expect.any(Object),
|
||||
DEFAULT_AGENT_DIR,
|
||||
{
|
||||
workspaceDir: "/tmp/workspace",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("applies provider runtime auth before streaming github-copilot BTW questions", async () => {
|
||||
|
||||
@@ -216,6 +216,7 @@ async function resolveRuntimeModel(params: {
|
||||
provider: string;
|
||||
model: string;
|
||||
agentDir: string;
|
||||
workspaceDir?: string;
|
||||
sessionEntry?: StoredSessionEntry;
|
||||
sessionStore?: Record<string, StoredSessionEntry>;
|
||||
sessionKey?: string;
|
||||
@@ -226,7 +227,8 @@ async function resolveRuntimeModel(params: {
|
||||
authProfileId?: string;
|
||||
authProfileIdSource?: "auto" | "user";
|
||||
}> {
|
||||
await ensureOpenClawModelsJson(params.cfg, params.agentDir);
|
||||
const modelsOptions = params.workspaceDir ? { workspaceDir: params.workspaceDir } : undefined;
|
||||
await ensureOpenClawModelsJson(params.cfg, params.agentDir, modelsOptions);
|
||||
const authStorage = discoverAuthStorage(params.agentDir);
|
||||
const modelRegistry = discoverModels(authStorage, params.agentDir);
|
||||
const model = resolveModelWithRegistry({
|
||||
@@ -319,11 +321,17 @@ export async function runBtwSideQuestion(
|
||||
throw new Error("No active session context.");
|
||||
}
|
||||
|
||||
const sessionAgentId = resolveSessionAgentId({
|
||||
sessionKey: params.sessionKey,
|
||||
config: params.cfg,
|
||||
});
|
||||
const workspaceDir = resolveAgentWorkspaceDir(params.cfg, sessionAgentId);
|
||||
const { model, authProfileId } = await resolveRuntimeModel({
|
||||
cfg: params.cfg,
|
||||
provider: params.provider,
|
||||
model: params.model,
|
||||
agentDir: params.agentDir,
|
||||
workspaceDir,
|
||||
sessionEntry: params.sessionEntry,
|
||||
sessionStore: params.sessionStore,
|
||||
sessionKey: params.sessionKey,
|
||||
@@ -341,11 +349,6 @@ export async function runBtwSideQuestion(
|
||||
apiKeyInfo.mode === "aws-sdk" && !apiKeyInfo.apiKey
|
||||
? undefined
|
||||
: requireApiKey(apiKeyInfo, model.provider);
|
||||
const sessionAgentId = resolveSessionAgentId({
|
||||
sessionKey: params.sessionKey,
|
||||
config: params.cfg,
|
||||
});
|
||||
const workspaceDir = resolveAgentWorkspaceDir(params.cfg, sessionAgentId);
|
||||
if (apiKey) {
|
||||
const preparedAuth = await prepareProviderRuntimeAuth({
|
||||
provider: model.provider,
|
||||
|
||||
@@ -482,7 +482,9 @@ async function compactEmbeddedPiSessionDirectOnce(
|
||||
};
|
||||
};
|
||||
const agentDir = params.agentDir ?? resolveOpenClawAgentDir();
|
||||
await ensureOpenClawModelsJson(params.config, agentDir);
|
||||
await ensureOpenClawModelsJson(params.config, agentDir, {
|
||||
workspaceDir: resolvedWorkspace,
|
||||
});
|
||||
const { model, error, authStorage, modelRegistry } = await resolveModelAsync(
|
||||
provider,
|
||||
modelId,
|
||||
|
||||
@@ -503,7 +503,9 @@ export async function runEmbeddedPiAgent(
|
||||
dynamicModelResolution.model || pluginHarnessOwnsTransport
|
||||
? dynamicModelResolution
|
||||
: await (async () => {
|
||||
await ensureOpenClawModelsJson(params.config, agentDir);
|
||||
await ensureOpenClawModelsJson(params.config, agentDir, {
|
||||
workspaceDir: resolvedWorkspace,
|
||||
});
|
||||
return await resolveModelAsync(provider, modelId, agentDir, params.config);
|
||||
})();
|
||||
const { model, error, authStorage, modelRegistry } = modelResolution;
|
||||
|
||||
@@ -394,17 +394,31 @@ describe("createPdfTool", () => {
|
||||
|
||||
it("uses native PDF path without eager extraction", async () => {
|
||||
await withTempPdfAgentDir(async (agentDir) => {
|
||||
const workspaceDir = path.join(agentDir, "workspace");
|
||||
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });
|
||||
vi.spyOn(pdfNativeProviders, "anthropicAnalyzePdf").mockResolvedValue("native summary");
|
||||
const extractSpy = vi.spyOn(pdfExtractModule, "extractPdfContent");
|
||||
const cfg = withPdfModel(ANTHROPIC_PDF_MODEL);
|
||||
const tool = requirePdfTool((await loadCreatePdfTool())({ config: cfg, agentDir }));
|
||||
const tool = requirePdfTool(
|
||||
(await loadCreatePdfTool())({ config: cfg, agentDir, workspaceDir }),
|
||||
);
|
||||
|
||||
const result = await tool.execute("t1", {
|
||||
prompt: "summarize",
|
||||
pdf: "/tmp/doc.pdf",
|
||||
});
|
||||
|
||||
expect(modelsConfig.ensureOpenClawModelsJson).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
agents: expect.objectContaining({
|
||||
defaults: expect.objectContaining({
|
||||
pdfModel: { primary: ANTHROPIC_PDF_MODEL },
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
agentDir,
|
||||
{ workspaceDir },
|
||||
);
|
||||
expect(extractSpy).not.toHaveBeenCalled();
|
||||
expect(result).toMatchObject({
|
||||
content: [{ type: "text", text: "native summary" }],
|
||||
|
||||
@@ -127,6 +127,7 @@ type PdfSandboxConfig = {
|
||||
async function runPdfPrompt(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
agentDir: string;
|
||||
workspaceDir?: string;
|
||||
pdfModelConfig: ImageModelConfig;
|
||||
modelOverride?: string;
|
||||
prompt: string;
|
||||
@@ -142,7 +143,8 @@ async function runPdfPrompt(params: {
|
||||
}> {
|
||||
const effectiveCfg = applyImageModelConfigDefaults(params.cfg, params.pdfModelConfig);
|
||||
|
||||
await ensureOpenClawModelsJson(effectiveCfg, params.agentDir);
|
||||
const modelsOptions = params.workspaceDir ? { workspaceDir: params.workspaceDir } : undefined;
|
||||
await ensureOpenClawModelsJson(effectiveCfg, params.agentDir, modelsOptions);
|
||||
const authStorage = discoverAuthStorage(params.agentDir);
|
||||
const modelRegistry = discoverModels(authStorage, params.agentDir);
|
||||
|
||||
@@ -482,6 +484,7 @@ export function createPdfTool(options?: {
|
||||
const result = await runPdfPrompt({
|
||||
cfg: options?.config,
|
||||
agentDir,
|
||||
...(options?.workspaceDir ? { workspaceDir: options.workspaceDir } : {}),
|
||||
pdfModelConfig,
|
||||
modelOverride,
|
||||
prompt: promptRaw,
|
||||
|
||||
Reference in New Issue
Block a user