mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-27 08:28:14 +00:00
fix(runtime): drop legacy x_search auth shim
This commit is contained in:
@@ -80,6 +80,42 @@ describe("legacy x_search config migration", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("moves legacy x_search SecretRefs into the xai plugin auth slot unchanged", () => {
|
||||||
|
const res = migrateLegacyXSearchConfig({
|
||||||
|
tools: {
|
||||||
|
web: {
|
||||||
|
x_search: {
|
||||||
|
apiKey: {
|
||||||
|
source: "env",
|
||||||
|
provider: "default",
|
||||||
|
id: "X_SEARCH_KEY_REF",
|
||||||
|
},
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
} as Record<string, unknown>,
|
||||||
|
},
|
||||||
|
} as OpenClawConfig);
|
||||||
|
|
||||||
|
expect((res.config.tools?.web as Record<string, unknown> | undefined)?.x_search).toEqual({
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
expect(res.config.plugins?.entries?.xai).toEqual({
|
||||||
|
enabled: true,
|
||||||
|
config: {
|
||||||
|
webSearch: {
|
||||||
|
apiKey: {
|
||||||
|
source: "env",
|
||||||
|
provider: "default",
|
||||||
|
id: "X_SEARCH_KEY_REF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.changes).toEqual([
|
||||||
|
"Moved tools.web.x_search.apiKey → plugins.entries.xai.config.webSearch.apiKey.",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("does nothing for knob-only x_search config without a legacy apiKey", () => {
|
it("does nothing for knob-only x_search config without a legacy apiKey", () => {
|
||||||
const config = {
|
const config = {
|
||||||
tools: {
|
tools: {
|
||||||
|
|||||||
@@ -651,6 +651,41 @@ describe("config strict validation", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("accepts legacy x_search SecretRefs via auto-migration and reports legacyIssues", async () => {
|
||||||
|
await withTempHome(async (home) => {
|
||||||
|
await writeOpenClawConfig(home, {
|
||||||
|
tools: {
|
||||||
|
web: {
|
||||||
|
x_search: {
|
||||||
|
apiKey: {
|
||||||
|
source: "env",
|
||||||
|
provider: "default",
|
||||||
|
id: "X_SEARCH_KEY_REF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const snap = await readConfigFileSnapshot();
|
||||||
|
|
||||||
|
expect(snap.valid).toBe(true);
|
||||||
|
expect(snap.legacyIssues.some((issue) => issue.path === "tools.web.x_search.apiKey")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(snap.sourceConfig.plugins?.entries?.xai?.config?.webSearch).toMatchObject({
|
||||||
|
apiKey: {
|
||||||
|
source: "env",
|
||||||
|
provider: "default",
|
||||||
|
id: "X_SEARCH_KEY_REF",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
(snap.sourceConfig.tools?.web?.x_search as Record<string, unknown> | undefined)?.apiKey,
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("accepts legacy thread binding ttlHours via auto-migration and reports legacyIssues", async () => {
|
it("accepts legacy thread binding ttlHours via auto-migration and reports legacyIssues", async () => {
|
||||||
await withTempHome(async (home) => {
|
await withTempHome(async (home) => {
|
||||||
await writeOpenClawConfig(home, {
|
await writeOpenClawConfig(home, {
|
||||||
|
|||||||
@@ -382,16 +382,6 @@ export async function resolveRuntimeWebTools(params: {
|
|||||||
|
|
||||||
const sourceTools = isRecord(params.sourceConfig.tools) ? params.sourceConfig.tools : undefined;
|
const sourceTools = isRecord(params.sourceConfig.tools) ? params.sourceConfig.tools : undefined;
|
||||||
const sourceWeb = isRecord(sourceTools?.web) ? sourceTools.web : undefined;
|
const sourceWeb = isRecord(sourceTools?.web) ? sourceTools.web : undefined;
|
||||||
const resolvedTools = isRecord(params.resolvedConfig.tools)
|
|
||||||
? params.resolvedConfig.tools
|
|
||||||
: undefined;
|
|
||||||
const resolvedWeb = isRecord(resolvedTools?.web) ? resolvedTools.web : undefined;
|
|
||||||
const legacyXSearchSourceRaw: unknown = sourceWeb?.x_search;
|
|
||||||
const legacyXSearchResolvedRaw: unknown = resolvedWeb?.x_search;
|
|
||||||
const legacyXSearchSource = isRecord(legacyXSearchSourceRaw) ? legacyXSearchSourceRaw : undefined;
|
|
||||||
const legacyXSearchResolved = isRecord(legacyXSearchResolvedRaw)
|
|
||||||
? legacyXSearchResolvedRaw
|
|
||||||
: undefined;
|
|
||||||
if (!sourceWeb && !hasPluginWebToolConfig(params.sourceConfig)) {
|
if (!sourceWeb && !hasPluginWebToolConfig(params.sourceConfig)) {
|
||||||
return {
|
return {
|
||||||
search: {
|
search: {
|
||||||
@@ -405,24 +395,6 @@ export async function resolveRuntimeWebTools(params: {
|
|||||||
diagnostics,
|
diagnostics,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
legacyXSearchSource &&
|
|
||||||
legacyXSearchResolved &&
|
|
||||||
Object.prototype.hasOwnProperty.call(legacyXSearchSource, "apiKey")
|
|
||||||
) {
|
|
||||||
const apiKey = legacyXSearchSource["apiKey"];
|
|
||||||
const resolution = await resolveSecretInputWithEnvFallback({
|
|
||||||
sourceConfig: params.sourceConfig,
|
|
||||||
context: params.context,
|
|
||||||
defaults,
|
|
||||||
value: apiKey,
|
|
||||||
path: "tools.web.x_search.apiKey",
|
|
||||||
envVars: ["XAI_API_KEY"],
|
|
||||||
});
|
|
||||||
if (resolution.value) {
|
|
||||||
legacyXSearchResolved["apiKey"] = resolution.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const search = isRecord(sourceWeb?.search) ? sourceWeb.search : undefined;
|
const search = isRecord(sourceWeb?.search) ? sourceWeb.search : undefined;
|
||||||
const rawProvider =
|
const rawProvider =
|
||||||
typeof search?.provider === "string" ? search.provider.trim().toLowerCase() : "";
|
typeof search?.provider === "string" ? search.provider.trim().toLowerCase() : "";
|
||||||
|
|||||||
@@ -1947,7 +1947,7 @@ describe("secrets runtime snapshot", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps legacy x_search SecretRefs in place until doctor repairs them", async () => {
|
it("leaves legacy x_search SecretRefs untouched so doctor owns the migration", async () => {
|
||||||
const snapshot = await prepareSecretsRuntimeSnapshot({
|
const snapshot = await prepareSecretsRuntimeSnapshot({
|
||||||
config: asConfig({
|
config: asConfig({
|
||||||
tools: {
|
tools: {
|
||||||
@@ -1968,45 +1968,13 @@ describe("secrets runtime snapshot", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect((snapshot.config.tools?.web as Record<string, unknown> | undefined)?.x_search).toEqual({
|
expect((snapshot.config.tools?.web as Record<string, unknown> | undefined)?.x_search).toEqual({
|
||||||
apiKey: "xai-runtime-key",
|
apiKey: { source: "env", provider: "default", id: "X_SEARCH_KEY_REF" },
|
||||||
enabled: true,
|
enabled: true,
|
||||||
model: "grok-4-1-fast",
|
model: "grok-4-1-fast",
|
||||||
});
|
});
|
||||||
expect(snapshot.config.plugins?.entries?.xai).toBeUndefined();
|
expect(snapshot.config.plugins?.entries?.xai).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("still resolves legacy x_search auth in place even when unrelated legacy config is present", async () => {
|
|
||||||
const snapshot = await prepareSecretsRuntimeSnapshot({
|
|
||||||
config: asConfig({
|
|
||||||
tools: {
|
|
||||||
web: {
|
|
||||||
x_search: {
|
|
||||||
apiKey: { source: "env", provider: "default", id: "X_SEARCH_KEY_REF" },
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
channels: {
|
|
||||||
telegram: {
|
|
||||||
groupMentionsOnly: true,
|
|
||||||
groups: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
env: {
|
|
||||||
X_SEARCH_KEY_REF: "xai-runtime-key-invalid-config",
|
|
||||||
},
|
|
||||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
|
||||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect((snapshot.config.tools?.web as Record<string, unknown> | undefined)?.x_search).toEqual({
|
|
||||||
apiKey: "xai-runtime-key-invalid-config",
|
|
||||||
enabled: true,
|
|
||||||
});
|
|
||||||
expect(snapshot.config.plugins?.entries?.xai).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not force-enable xai at runtime for knob-only x_search config", async () => {
|
it("does not force-enable xai at runtime for knob-only x_search config", async () => {
|
||||||
const snapshot = await prepareSecretsRuntimeSnapshot({
|
const snapshot = await prepareSecretsRuntimeSnapshot({
|
||||||
config: asConfig({
|
config: asConfig({
|
||||||
|
|||||||
Reference in New Issue
Block a user