












@@ -111,6 +111,46 @@ function modelIdNormalizationSnapshot() {
111111};
112112}
113113114+function manifestModelCatalogSnapshot(model: {
115+id: string;
116+name?: string;
117+input?: Array<"text" | "image">;
118+reasoning?: boolean;
119+contextWindow?: number;
120+}) {
121+return {
122+policyHash: "policy",
123+index: {
124+policyHash: "policy",
125+plugins: [
126+{
127+pluginId: "external-provider",
128+enabled: true,
129+origin: "global",
130+},
131+],
132+},
133+plugins: [
134+{
135+id: "external-provider",
136+origin: "global",
137+modelCatalog: {
138+providers: {
139+external: {
140+models: [
141+{
142+name: model.id,
143+ ...model,
144+},
145+],
146+},
147+},
148+},
149+},
150+],
151+};
152+}
153+114154function configuredModel(id: string) {
115155return {
116156 id,
@@ -896,40 +936,13 @@ describe("loadModelCatalog", () => {
896936});
897937898938it("loads manifest catalog rows from the current metadata snapshot without provider runtime", () => {
899-const snapshot = {
900-policyHash: "policy",
901-index: {
902-policyHash: "policy",
903-plugins: [
904-{
905-pluginId: "external-provider",
906-enabled: true,
907-origin: "global",
908-},
909-],
910-},
911-plugins: [
912-{
913-id: "external-provider",
914-origin: "global",
915-modelCatalog: {
916-providers: {
917-external: {
918-models: [
919-{
920-id: "external-fast",
921-name: "External Fast",
922-input: ["text", "image"],
923-reasoning: true,
924-contextWindow: 32000,
925-},
926-],
927-},
928-},
929-},
930-},
931-],
932-};
939+const snapshot = manifestModelCatalogSnapshot({
940+id: "external-fast",
941+name: "External Fast",
942+input: ["text", "image"],
943+reasoning: true,
944+contextWindow: 32000,
945+});
933946currentPluginMetadataSnapshotMock.mockReturnValue(snapshot);
934947935948const result = loadManifestModelCatalog({ config: {} as OpenClawConfig });
@@ -948,6 +961,41 @@ describe("loadModelCatalog", () => {
948961]);
949962});
950963964+it("reuses planned manifest catalog rows for the same config and metadata snapshot", () => {
965+const config = {} as OpenClawConfig;
966+const snapshot = manifestModelCatalogSnapshot({ id: "external-fast" });
967+currentPluginMetadataSnapshotMock.mockReturnValue(snapshot);
968+969+const first = loadManifestModelCatalog({ config });
970+const second = loadManifestModelCatalog({ config });
971+972+expect(second).toBe(first);
973+expect(first).toEqual([
974+{
975+provider: "external",
976+id: "external-fast",
977+name: "external-fast",
978+input: ["text"],
979+reasoning: false,
980+},
981+]);
982+expect(loadPluginMetadataSnapshotMock).not.toHaveBeenCalled();
983+});
984+985+it("refreshes manifest catalog rows when the metadata snapshot changes", () => {
986+const config = {} as OpenClawConfig;
987+currentPluginMetadataSnapshotMock
988+.mockReturnValueOnce(manifestModelCatalogSnapshot({ id: "external-fast" }))
989+.mockReturnValue(manifestModelCatalogSnapshot({ id: "external-slow" }));
990+991+const first = loadManifestModelCatalog({ config });
992+const second = loadManifestModelCatalog({ config });
993+994+expect(second).not.toBe(first);
995+expect(first[0]?.id).toBe("external-fast");
996+expect(second[0]?.id).toBe("external-slow");
997+});
998+951999it("lets read-only manifest catalog reuse the current workspace-scoped snapshot", () => {
9521000loadManifestModelCatalog({
9531001config: {} as OpenClawConfig,
此內容由慣性聚合(RSS閱讀器)自動聚合整理,僅供閱讀參考。 原文來自 — 版權歸原作者所有。