feat(grokbuild): add first-class Grok Build support (#5453)

* feat(grokbuild): add backend integration

* feat(grokbuild): add provider and management UI

* test(grokbuild): cover configuration and integrations

* fix(grokbuild): address backend review feedback

* fix(grokbuild): complete UI review feedback

* feat(grokbuild): add CLI lifecycle management

* fix(grokbuild): align provider icon fallback

* test(grokbuild): cover provider icon persistence
This commit is contained in:
Thefool
2026-07-17 15:50:50 +08:00
committed by GitHub
parent f6e37ed994
commit 1c0ee0c58a
112 changed files with 4530 additions and 246 deletions
@@ -48,6 +48,7 @@ const createSettings = (
enableClaudePluginIntegration: false,
claudeConfigDir: "/claude/custom",
codexConfigDir: "/codex/custom",
grokConfigDir: "/grok/custom",
language: "zh",
...overrides,
});
@@ -68,6 +69,7 @@ describe("useDirectorySettings", () => {
if (app === "claude") return "/remote/claude";
if (app === "codex") return "/remote/codex";
if (app === "gemini") return "/remote/gemini";
if (app === "grokbuild") return "/remote/grok";
if (app === "opencode") return "/remote/opencode";
if (app === "openclaw") return "/remote/openclaw";
return "/remote/hermes";
@@ -90,6 +92,7 @@ describe("useDirectorySettings", () => {
claude: "/remote/claude",
codex: "/remote/codex",
gemini: "/remote/gemini",
grokbuild: "/remote/grok",
opencode: "/remote/opencode",
openclaw: "/remote/openclaw",
hermes: "/remote/hermes",
@@ -249,6 +252,7 @@ describe("useDirectorySettings", () => {
claude: "/server/claude",
codex: "/server/codex",
gemini: "/server/gemini",
grokbuild: "/server/grok",
opencode: "/server/opencode",
openclaw: "/server/openclaw",
});
@@ -257,6 +261,7 @@ describe("useDirectorySettings", () => {
expect(result.current.resolvedDirs.claude).toBe("/server/claude");
expect(result.current.resolvedDirs.codex).toBe("/server/codex");
expect(result.current.resolvedDirs.gemini).toBe("/server/gemini");
expect(result.current.resolvedDirs.grokbuild).toBe("/server/grok");
expect(result.current.resolvedDirs.opencode).toBe("/server/opencode");
expect(result.current.resolvedDirs.openclaw).toBe("/server/openclaw");
});
+36
View File
@@ -264,6 +264,42 @@ describe("useProviderActions", () => {
expect(switchProviderMutateAsync).toHaveBeenCalledWith(provider.id);
});
it("warns for Grok providers that require the Responses router", async () => {
switchProviderMutateAsync.mockResolvedValue(undefined);
const { wrapper } = createWrapper();
const providers = [
createProvider({
id: "grok-chat",
category: "custom",
meta: { apiFormat: "openai_chat" },
}),
createProvider({
id: "grok-anthropic",
category: "custom",
meta: { apiFormat: "anthropic" },
}),
createProvider({
id: "grok-full-url",
category: "custom",
meta: { isFullUrl: true },
}),
];
const { result } = renderHook(
() => useProviderActions("grokbuild", false),
{ wrapper },
);
for (const provider of providers) {
await act(async () => {
await result.current.switchProvider(provider);
});
}
expect(toastWarningMock).toHaveBeenCalledTimes(3);
expect(switchProviderMutateAsync).toHaveBeenCalledTimes(3);
});
it("allows the built-in Codex official provider during takeover", async () => {
switchProviderMutateAsync.mockResolvedValueOnce(undefined);
const { wrapper } = createWrapper();
+2 -1
View File
@@ -81,6 +81,7 @@ describe("useProxyStatus", () => {
claude: false,
codex: false,
gemini: false,
grokbuild: false,
opencode: false,
openclaw: false,
});
@@ -115,4 +116,4 @@ describe("useProxyStatus", () => {
{ closeButton: true },
);
});
});
});