

























@@ -1,6 +1,8 @@
11import fs from "node:fs/promises";
22import path from "node:path";
33import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
4+import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
5+import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
46import {
57CUSTOM_PROXY_MODELS_CONFIG,
68installModelsConfigTestHooks,
@@ -13,15 +15,63 @@ const planOpenClawModelsJsonMock = vi.fn();
1315installModelsConfigTestHooks();
14161517let ensureOpenClawModelsJson: typeof import("./models-config.js").ensureOpenClawModelsJson;
18+let clearCurrentPluginMetadataSnapshot: typeof import("../plugins/current-plugin-metadata-snapshot.js").clearCurrentPluginMetadataSnapshot;
19+let setCurrentPluginMetadataSnapshot: typeof import("../plugins/current-plugin-metadata-snapshot.js").setCurrentPluginMetadataSnapshot;
20+21+function createPluginMetadataSnapshot(workspaceDir: string): PluginMetadataSnapshot {
22+const policyHash = resolveInstalledPluginIndexPolicyHash({});
23+return {
24+ policyHash,
25+ workspaceDir,
26+index: {
27+version: 1,
28+hostContractVersion: "test",
29+compatRegistryVersion: "test",
30+migrationVersion: 1,
31+ policyHash,
32+generatedAtMs: 1,
33+installRecords: {},
34+plugins: [],
35+diagnostics: [],
36+},
37+registryDiagnostics: [],
38+manifestRegistry: { plugins: [], diagnostics: [] },
39+plugins: [],
40+diagnostics: [],
41+byPluginId: new Map(),
42+normalizePluginId: (pluginId) => pluginId,
43+owners: {
44+channels: new Map(),
45+channelConfigs: new Map(),
46+providers: new Map(),
47+modelCatalogProviders: new Map(),
48+cliBackends: new Map(),
49+setupProviders: new Map(),
50+commandAliases: new Map(),
51+contracts: new Map(),
52+},
53+metrics: {
54+registrySnapshotMs: 0,
55+manifestRegistryMs: 0,
56+ownerMapsMs: 0,
57+totalMs: 0,
58+indexPluginCount: 0,
59+manifestPluginCount: 0,
60+},
61+};
62+}
16631764beforeAll(async () => {
1865vi.doMock("./models-config.plan.js", () => ({
1966planOpenClawModelsJson: (...args: unknown[]) => planOpenClawModelsJsonMock(...args),
2067}));
2168({ ensureOpenClawModelsJson } = await import("./models-config.js"));
69+({ clearCurrentPluginMetadataSnapshot, setCurrentPluginMetadataSnapshot } =
70+await import("../plugins/current-plugin-metadata-snapshot.js"));
2271});
23722473beforeEach(() => {
74+clearCurrentPluginMetadataSnapshot();
2575planOpenClawModelsJsonMock
2676.mockReset()
2777.mockImplementation(async (params: { cfg?: typeof CUSTOM_PROXY_MODELS_CONFIG }) => ({
@@ -31,6 +81,38 @@ beforeEach(() => {
3181});
32823383describe("models-config write serialization", () => {
84+it("does not reuse default workspace plugin metadata for explicit agent dirs without workspace", async () => {
85+await withModelsTempHome(async (home) => {
86+const snapshot = createPluginMetadataSnapshot(path.join(home, "default-workspace"));
87+setCurrentPluginMetadataSnapshot(snapshot, { config: {} });
88+const agentDir = path.join(home, "agent-non-default");
89+90+await ensureOpenClawModelsJson({}, agentDir);
91+92+expect(planOpenClawModelsJsonMock).toHaveBeenCalledWith(
93+expect.not.objectContaining({ pluginMetadataSnapshot: snapshot }),
94+);
95+});
96+});
97+98+it("reuses current plugin metadata for explicit agent dirs with matching workspace", async () => {
99+await withModelsTempHome(async (home) => {
100+const workspaceDir = path.join(home, "agent-workspace");
101+const snapshot = createPluginMetadataSnapshot(workspaceDir);
102+setCurrentPluginMetadataSnapshot(snapshot, { config: {} });
103+const agentDir = path.join(home, "agent-non-default");
104+105+await ensureOpenClawModelsJson({}, agentDir, { workspaceDir });
106+107+expect(planOpenClawModelsJsonMock).toHaveBeenCalledWith(
108+expect.objectContaining({
109+ workspaceDir,
110+pluginMetadataSnapshot: snapshot,
111+}),
112+);
113+});
114+});
115+34116it("serializes concurrent models.json writes to avoid overlap", async () => {
35117await withModelsTempHome(async () => {
36118const first = structuredClone(CUSTOM_PROXY_MODELS_CONFIG);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。