mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-29 16:54:30 +00:00
feat: finish xai provider integration
This commit is contained in:
@@ -7,6 +7,7 @@ import { resolveBundledPluginsDir } from "./bundled-dir.js";
|
||||
const tempDirs: string[] = [];
|
||||
const originalCwd = process.cwd();
|
||||
const originalBundledDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
const originalVitest = process.env.VITEST;
|
||||
|
||||
function makeRepoRoot(prefix: string): string {
|
||||
const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||
@@ -21,6 +22,11 @@ afterEach(() => {
|
||||
} else {
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = originalBundledDir;
|
||||
}
|
||||
if (originalVitest === undefined) {
|
||||
delete process.env.VITEST;
|
||||
} else {
|
||||
process.env.VITEST = originalVitest;
|
||||
}
|
||||
for (const dir of tempDirs.splice(0, tempDirs.length)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
@@ -43,4 +49,23 @@ describe("resolveBundledPluginsDir", () => {
|
||||
fs.realpathSync(path.join(repoRoot, "dist-runtime", "extensions")),
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers source extensions under vitest to avoid stale staged plugins", () => {
|
||||
const repoRoot = makeRepoRoot("openclaw-bundled-dir-vitest-");
|
||||
fs.mkdirSync(path.join(repoRoot, "extensions"), { recursive: true });
|
||||
fs.mkdirSync(path.join(repoRoot, "dist-runtime", "extensions"), { recursive: true });
|
||||
fs.mkdirSync(path.join(repoRoot, "dist", "extensions"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(repoRoot, "package.json"),
|
||||
`${JSON.stringify({ name: "openclaw" }, null, 2)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
|
||||
process.chdir(repoRoot);
|
||||
process.env.VITEST = "true";
|
||||
|
||||
expect(fs.realpathSync(resolveBundledPluginsDir() ?? "")).toBe(
|
||||
fs.realpathSync(path.join(repoRoot, "extensions")),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,8 @@ export function resolveBundledPluginsDir(env: NodeJS.ProcessEnv = process.env):
|
||||
return resolveUserPath(override, env);
|
||||
}
|
||||
|
||||
const preferSourceCheckout = Boolean(env.VITEST);
|
||||
|
||||
try {
|
||||
const packageRoots = [
|
||||
resolveOpenClawPackageRootSync({ cwd: process.cwd() }),
|
||||
@@ -18,6 +20,10 @@ export function resolveBundledPluginsDir(env: NodeJS.ProcessEnv = process.env):
|
||||
(entry, index, all): entry is string => Boolean(entry) && all.indexOf(entry) === index,
|
||||
);
|
||||
for (const packageRoot of packageRoots) {
|
||||
const sourceExtensionsDir = path.join(packageRoot, "extensions");
|
||||
if (preferSourceCheckout && fs.existsSync(sourceExtensionsDir)) {
|
||||
return sourceExtensionsDir;
|
||||
}
|
||||
// Local source checkouts stage a runtime-complete bundled plugin tree under
|
||||
// dist-runtime/. Prefer that over source extensions only when the paired
|
||||
// dist/ tree exists; otherwise wrappers can drift ahead of the last build.
|
||||
|
||||
@@ -429,6 +429,120 @@ describe("provider runtime contract", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("xai", () => {
|
||||
it("owns Grok forward-compat resolution for newer fast models", () => {
|
||||
const provider = requireProviderContractProvider("xai");
|
||||
const model = provider.resolveDynamicModel?.({
|
||||
provider: "xai",
|
||||
modelId: "grok-4-1-fast-reasoning",
|
||||
modelRegistry: {
|
||||
find: () => null,
|
||||
} as never,
|
||||
providerConfig: {
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.x.ai/v1",
|
||||
},
|
||||
});
|
||||
|
||||
expect(model).toMatchObject({
|
||||
id: "grok-4-1-fast-reasoning",
|
||||
provider: "xai",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.x.ai/v1",
|
||||
reasoning: true,
|
||||
contextWindow: 2_000_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("owns xai modern-model matching without accepting multi-agent ids", () => {
|
||||
const provider = requireProviderContractProvider("xai");
|
||||
|
||||
expect(
|
||||
provider.isModernModelRef?.({
|
||||
provider: "xai",
|
||||
modelId: "grok-4-1-fast-reasoning",
|
||||
} as never),
|
||||
).toBe(true);
|
||||
expect(
|
||||
provider.isModernModelRef?.({
|
||||
provider: "xai",
|
||||
modelId: "grok-4.20-multi-agent-experimental-beta-0304",
|
||||
} as never),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("owns direct xai compat flags on resolved models", () => {
|
||||
const provider = requireProviderContractProvider("xai");
|
||||
|
||||
expect(
|
||||
provider.normalizeResolvedModel?.({
|
||||
provider: "xai",
|
||||
modelId: "grok-4-1-fast",
|
||||
model: createModel({
|
||||
id: "grok-4-1-fast",
|
||||
provider: "xai",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.x.ai/v1",
|
||||
}),
|
||||
} as never),
|
||||
).toMatchObject({
|
||||
compat: {
|
||||
toolSchemaProfile: "xai",
|
||||
nativeWebSearchTool: true,
|
||||
toolCallArgumentsEncoding: "html-entities",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("openrouter", () => {
|
||||
it("owns xai downstream compat flags for x-ai routed models", () => {
|
||||
const provider = requireProviderContractProvider("openrouter");
|
||||
expect(
|
||||
provider.normalizeResolvedModel?.({
|
||||
provider: "openrouter",
|
||||
modelId: "x-ai/grok-4-1-fast",
|
||||
model: createModel({
|
||||
id: "x-ai/grok-4-1-fast",
|
||||
provider: "openrouter",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
}),
|
||||
}),
|
||||
).toMatchObject({
|
||||
compat: {
|
||||
toolSchemaProfile: "xai",
|
||||
nativeWebSearchTool: true,
|
||||
toolCallArgumentsEncoding: "html-entities",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("venice", () => {
|
||||
it("owns xai downstream compat flags for grok-backed Venice models", () => {
|
||||
const provider = requireProviderContractProvider("venice");
|
||||
expect(
|
||||
provider.normalizeResolvedModel?.({
|
||||
provider: "venice",
|
||||
modelId: "grok-41-fast",
|
||||
model: createModel({
|
||||
id: "grok-41-fast",
|
||||
provider: "venice",
|
||||
api: "openai-completions",
|
||||
baseUrl: "https://api.venice.ai/api/v1",
|
||||
}),
|
||||
}),
|
||||
).toMatchObject({
|
||||
compat: {
|
||||
toolSchemaProfile: "xai",
|
||||
nativeWebSearchTool: true,
|
||||
toolCallArgumentsEncoding: "html-entities",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("openai-codex", () => {
|
||||
it("owns refresh fallback for accountId extraction failures", async () => {
|
||||
const provider = requireProviderContractProvider("openai-codex");
|
||||
|
||||
Reference in New Issue
Block a user