FN-6401: add built-in Z.ai GLM-5.2 support
Add Z.ai's built-in provider registration so GLM-5.2 is selectable across Fusion model settings. - Define and export a shared Z.ai provider registration with existing GLM models plus GLM-5.2. - Register the built-in provider for CLI server and engine pi model registries. - Cover provider availability and CLI auth-provider wrapping with focused tests. - Document Z.ai model selection and add a minor changeset. Files changed: .changeset/FN-6401-glm-5-2.md | 5 + docs/settings-reference.md | 2 + packages/cli/src/commands/__tests__/daemon.test.ts | 11 ++ .../cli/src/commands/__tests__/dashboard.test.ts | 13 +++ packages/cli/src/commands/__tests__/serve.test.ts | 11 ++ packages/cli/src/commands/daemon.ts | 8 ++ packages/cli/src/commands/dashboard.ts | 8 ++ packages/cli/src/commands/serve.ts | 8 ++ packages/core/src/__tests__/zai-provider.test.ts | 48 ++++++++ packages/core/src/index.ts | 2 + packages/core/src/zai-provider.ts | 125 +++++++++++++++++++++ .../src/__tests__/pi-create-fn-agent.test.ts | 5 +- packages/engine/src/pi.ts | 20 +++- 13 files changed, 264 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-6401 Fusion-Task-Lineage: e1f7a90d-0614-4d9f-826f-015605a08baa
This commit is contained in:
5
.changeset/FN-6401-glm-5-2.md
Normal file
5
.changeset/FN-6401-glm-5-2.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Enable Z.ai GLM-5.2 model selection.
|
||||||
@@ -801,6 +801,8 @@ Short-lived token bounds are enforced server-side:
|
|||||||
|
|
||||||
Fusion resolves task models through workflow-backed lane values first, then global lane defaults, then the project/global default model fallback. The common workflow lanes are stored as setting values on the project's default workflow and can be edited with dropdown controls from Settings -> Project Models -> Default workflow model lanes (persisted by the Settings modal's primary Save) or from workflow editor -> Settings -> Values for declared workflow lanes and fallbacks.
|
Fusion resolves task models through workflow-backed lane values first, then global lane defaults, then the project/global default model fallback. The common workflow lanes are stored as setting values on the project's default workflow and can be edited with dropdown controls from Settings -> Project Models -> Default workflow model lanes (persisted by the Settings modal's primary Save) or from workflow editor -> Settings -> Values for declared workflow lanes and fallbacks.
|
||||||
|
|
||||||
|
Z.ai's built-in provider uses the existing `zai` auth entry / `ZAI_API_KEY` environment variable and includes `zai/glm-5.2` as a selectable model in the same dropdowns and workflow lane controls as the other built-in GLM models.
|
||||||
|
|
||||||
### Planning model
|
### Planning model
|
||||||
|
|
||||||
1. Per-task `planningModelProvider` + `planningModelId`
|
1. Per-task `planningModelProvider` + `planningModelId`
|
||||||
|
|||||||
@@ -682,6 +682,17 @@ describe("runDaemon", () => {
|
|||||||
await runDaemon({});
|
await runDaemon({});
|
||||||
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("registers built-in zai GLM-5.2 before refreshing models", async () => {
|
||||||
|
await runDaemon({});
|
||||||
|
|
||||||
|
expect(mocks.modelRegistry.registerProvider).toHaveBeenCalledWith("zai", expect.objectContaining({
|
||||||
|
models: expect.arrayContaining([expect.objectContaining({ id: "glm-5.2" })]),
|
||||||
|
}));
|
||||||
|
expect(mocks.modelRegistry.refresh).toHaveBeenCalled();
|
||||||
|
|
||||||
|
await triggerSignal("SIGINT");
|
||||||
|
});
|
||||||
const originalCwd = process.cwd;
|
const originalCwd = process.cwd;
|
||||||
const originalExit = process.exit;
|
const originalExit = process.exit;
|
||||||
|
|
||||||
|
|||||||
@@ -832,10 +832,23 @@ async function runDashboard(...args: Parameters<typeof runDashboardImpl>): Retur
|
|||||||
// ── Tests ───────────────────────────────────────────────────────────
|
// ── Tests ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
describe("runDashboard — startup model sync", () => {
|
describe("runDashboard — startup model sync", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
it("invokes shared startup model sync", async () => {
|
it("invokes shared startup model sync", async () => {
|
||||||
await runDashboard(0, { open: false });
|
await runDashboard(0, { open: false });
|
||||||
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("registers built-in zai GLM-5.2 before refreshing models", async () => {
|
||||||
|
await runDashboard(0, { open: false });
|
||||||
|
|
||||||
|
expect(mockModelRegistry.registerProvider).toHaveBeenCalledWith("zai", expect.objectContaining({
|
||||||
|
models: expect.arrayContaining([expect.objectContaining({ id: "glm-5.2" })]),
|
||||||
|
}));
|
||||||
|
expect(mockModelRegistry.refresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function resetGitHubMocks() {
|
function resetGitHubMocks() {
|
||||||
|
|||||||
@@ -752,6 +752,17 @@ describe("runServe", () => {
|
|||||||
await runServe(4040, {});
|
await runServe(4040, {});
|
||||||
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
expect(mockSyncStartupModels).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("registers built-in zai GLM-5.2 before refreshing models", async () => {
|
||||||
|
await runServe(0, {});
|
||||||
|
|
||||||
|
expect(mocks.modelRegistry.registerProvider).toHaveBeenCalledWith("zai", expect.objectContaining({
|
||||||
|
models: expect.arrayContaining([expect.objectContaining({ id: "glm-5.2" })]),
|
||||||
|
}));
|
||||||
|
expect(mocks.modelRegistry.refresh).toHaveBeenCalled();
|
||||||
|
|
||||||
|
await triggerSignal("SIGINT");
|
||||||
|
});
|
||||||
const originalCwd = process.cwd;
|
const originalCwd = process.cwd;
|
||||||
const originalOn = process.on;
|
const originalOn = process.on;
|
||||||
const originalExit = process.exit;
|
const originalExit = process.exit;
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
resolveGlobalDir,
|
resolveGlobalDir,
|
||||||
getEnabledPiExtensionPaths,
|
getEnabledPiExtensionPaths,
|
||||||
reconcileClaudeCliPaths,
|
reconcileClaudeCliPaths,
|
||||||
|
ZAI_PROVIDER_ID,
|
||||||
|
ZAI_PROVIDER_REGISTRATION,
|
||||||
} from "@fusion/core";
|
} from "@fusion/core";
|
||||||
import type { AutomationRunResult, ScheduledTask } from "@fusion/core";
|
import type { AutomationRunResult, ScheduledTask } from "@fusion/core";
|
||||||
import { createServer, GitHubClient, createSkillsAdapter, getProjectSettingsPath, loadTlsCredentialsFromEnv, registerGithubTrackingHook } from "@fusion/dashboard";
|
import { createServer, GitHubClient, createSkillsAdapter, getProjectSettingsPath, loadTlsCredentialsFromEnv, registerGithubTrackingHook } from "@fusion/dashboard";
|
||||||
@@ -552,6 +554,12 @@ export async function runDaemon(opts: DaemonOptions = {}) {
|
|||||||
]);
|
]);
|
||||||
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
||||||
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
||||||
|
try {
|
||||||
|
modelRegistry.registerProvider(ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
console.log(`[extensions] Failed to register built-in ${ZAI_PROVIDER_ID} provider: ${message}`);
|
||||||
|
}
|
||||||
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
||||||
|
|
||||||
// PackageManager may be used for skills adapter even if extension loading fails
|
// PackageManager may be used for skills adapter even if extension loading fails
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import {
|
|||||||
resolveColumnFlags,
|
resolveColumnFlags,
|
||||||
BUILTIN_CODING_WORKFLOW_IR,
|
BUILTIN_CODING_WORKFLOW_IR,
|
||||||
parseWorkflowIr,
|
parseWorkflowIr,
|
||||||
|
ZAI_PROVIDER_ID,
|
||||||
|
ZAI_PROVIDER_REGISTRATION,
|
||||||
type WorkflowIrColumn,
|
type WorkflowIrColumn,
|
||||||
type TraitFlags,
|
type TraitFlags,
|
||||||
} from "@fusion/core";
|
} from "@fusion/core";
|
||||||
@@ -1369,6 +1371,12 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
|||||||
]);
|
]);
|
||||||
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
||||||
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
||||||
|
try {
|
||||||
|
modelRegistry.registerProvider(ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
logSink.log(`Failed to register built-in ${ZAI_PROVIDER_ID} provider: ${message}`, "extensions");
|
||||||
|
}
|
||||||
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
||||||
|
|
||||||
// PackageManager may be used for skills adapter even if extension loading fails.
|
// PackageManager may be used for skills adapter even if extension loading fails.
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
GlobalSettingsStore,
|
GlobalSettingsStore,
|
||||||
resolveGlobalDir,
|
resolveGlobalDir,
|
||||||
getEnabledPiExtensionPaths,
|
getEnabledPiExtensionPaths,
|
||||||
|
ZAI_PROVIDER_ID,
|
||||||
|
ZAI_PROVIDER_REGISTRATION,
|
||||||
} from "@fusion/core";
|
} from "@fusion/core";
|
||||||
import type { AutomationRunResult, ScheduledTask } from "@fusion/core";
|
import type { AutomationRunResult, ScheduledTask } from "@fusion/core";
|
||||||
import { createServer, GitHubClient, createSkillsAdapter, getProjectSettingsPath, loadTlsCredentialsFromEnv, registerGithubTrackingHook } from "@fusion/dashboard";
|
import { createServer, GitHubClient, createSkillsAdapter, getProjectSettingsPath, loadTlsCredentialsFromEnv, registerGithubTrackingHook } from "@fusion/dashboard";
|
||||||
@@ -602,6 +604,12 @@ export async function runServe(
|
|||||||
]);
|
]);
|
||||||
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
const mergedAuthStorage = mergeAuthStorageReads(authStorage, [supplementalAuthStorage]);
|
||||||
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
const modelRegistry = ModelRegistry.create(mergedAuthStorage, getModelRegistryModelsPath());
|
||||||
|
try {
|
||||||
|
modelRegistry.registerProvider(ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
console.log(`[extensions] Failed to register built-in ${ZAI_PROVIDER_ID} provider: ${message}`);
|
||||||
|
}
|
||||||
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
const dashboardAuthStorage = wrapAuthStorageWithApiKeyProviders(mergedAuthStorage, modelRegistry);
|
||||||
|
|
||||||
// PackageManager may be used for skills adapter even if extension loading fails
|
// PackageManager may be used for skills adapter even if extension loading fails
|
||||||
|
|||||||
48
packages/core/src/__tests__/zai-provider.test.ts
Normal file
48
packages/core/src/__tests__/zai-provider.test.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION } from "../zai-provider.js";
|
||||||
|
|
||||||
|
const EXISTING_ZAI_MODELS = [
|
||||||
|
"glm-4.5-air",
|
||||||
|
"glm-4.7",
|
||||||
|
"glm-5-turbo",
|
||||||
|
"glm-5.1",
|
||||||
|
"glm-5v-turbo",
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("ZAI_PROVIDER_REGISTRATION", () => {
|
||||||
|
it("uses the existing zai auth surface and API endpoint", () => {
|
||||||
|
expect(ZAI_PROVIDER_ID).toBe("zai");
|
||||||
|
expect(ZAI_PROVIDER_REGISTRATION).toMatchObject({
|
||||||
|
name: "ZAI",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
apiKey: "$ZAI_API_KEY",
|
||||||
|
api: "openai-completions",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves existing built-in models and appends glm-5.2", () => {
|
||||||
|
const modelIds = ZAI_PROVIDER_REGISTRATION.models.map((model) => model.id);
|
||||||
|
|
||||||
|
expect(modelIds).toEqual([...EXISTING_ZAI_MODELS, "glm-5.2"]);
|
||||||
|
for (const id of EXISTING_ZAI_MODELS) {
|
||||||
|
expect(modelIds).toContain(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("registers GLM-5.2 with upstream model capabilities", () => {
|
||||||
|
expect(ZAI_PROVIDER_REGISTRATION.models.find((model) => model.id === "glm-5.2")).toMatchObject({
|
||||||
|
id: "glm-5.2",
|
||||||
|
name: "GLM-5.2",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1_000_000,
|
||||||
|
maxTokens: 131_072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -20,6 +20,8 @@ export { redactSecrets } from "./redact-secrets.js";
|
|||||||
export * from "./frontend-ux-policy.js";
|
export * from "./frontend-ux-policy.js";
|
||||||
export { MOCK_PROVIDER_ID } from "./mock-provider-constants.js";
|
export { MOCK_PROVIDER_ID } from "./mock-provider-constants.js";
|
||||||
export type { MockProviderId, MockSessionPurpose } from "./mock-provider-constants.js";
|
export type { MockProviderId, MockSessionPurpose } from "./mock-provider-constants.js";
|
||||||
|
export { ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION } from "./zai-provider.js";
|
||||||
|
export type { ZaiProviderRegistration } from "./zai-provider.js";
|
||||||
export {
|
export {
|
||||||
resolveWorktrunkSettings,
|
resolveWorktrunkSettings,
|
||||||
requiresWorktrunkInstallVerification,
|
requiresWorktrunkInstallVerification,
|
||||||
|
|||||||
125
packages/core/src/zai-provider.ts
Normal file
125
packages/core/src/zai-provider.ts
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
export const ZAI_PROVIDER_ID = "zai";
|
||||||
|
|
||||||
|
type ZaiModelInput = "text" | "image";
|
||||||
|
|
||||||
|
interface ZaiModelRegistration {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
reasoning: boolean;
|
||||||
|
input: ZaiModelInput[];
|
||||||
|
cost: {
|
||||||
|
input: number;
|
||||||
|
output: number;
|
||||||
|
cacheRead: number;
|
||||||
|
cacheWrite: number;
|
||||||
|
};
|
||||||
|
contextWindow: number;
|
||||||
|
maxTokens: number;
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: boolean;
|
||||||
|
thinkingFormat: "zai";
|
||||||
|
zaiToolStream?: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ZaiProviderRegistration {
|
||||||
|
name: string;
|
||||||
|
baseUrl: string;
|
||||||
|
apiKey: string;
|
||||||
|
api: "openai-completions";
|
||||||
|
models: ZaiModelRegistration[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// pi registerProvider() replaces the provider's model list, so keep every
|
||||||
|
// currently built-in Z.ai model here and append new models such as GLM-5.2.
|
||||||
|
export const ZAI_PROVIDER_REGISTRATION: ZaiProviderRegistration = {
|
||||||
|
name: "ZAI",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
apiKey: "$ZAI_API_KEY",
|
||||||
|
api: "openai-completions",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: "glm-4.5-air",
|
||||||
|
name: "GLM-4.5-Air",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 98304,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glm-4.7",
|
||||||
|
name: "GLM-4.7",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glm-5-turbo",
|
||||||
|
name: "GLM-5-Turbo",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glm-5v-turbo",
|
||||||
|
name: "GLM-5V-Turbo",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glm-5.2",
|
||||||
|
name: "GLM-5.2",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
compat: {
|
||||||
|
supportsDeveloperRole: false,
|
||||||
|
thinkingFormat: "zai",
|
||||||
|
zaiToolStream: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -1336,7 +1336,10 @@ describe("createFnAgent", () => {
|
|||||||
"/tmp",
|
"/tmp",
|
||||||
"/tmp/.fusion/disabled-auto-extension-discovery",
|
"/tmp/.fusion/disabled-auto-extension-discovery",
|
||||||
);
|
);
|
||||||
expect(registerProviderMock).toHaveBeenCalledWith("zai", expect.objectContaining({
|
expect(registerProviderMock).toHaveBeenNthCalledWith(1, "zai", expect.objectContaining({
|
||||||
|
models: expect.arrayContaining([expect.objectContaining({ id: "glm-5.2" })]),
|
||||||
|
}));
|
||||||
|
expect(registerProviderMock).toHaveBeenNthCalledWith(2, "zai", expect.objectContaining({
|
||||||
models: [{ id: "glm-5.1" }],
|
models: [{ id: "glm-5.1" }],
|
||||||
}));
|
}));
|
||||||
expect(refreshMock).toHaveBeenCalled();
|
expect(refreshMock).toHaveBeenCalled();
|
||||||
|
|||||||
@@ -34,7 +34,18 @@ import {
|
|||||||
type AgentSession,
|
type AgentSession,
|
||||||
type ToolDefinition,
|
type ToolDefinition,
|
||||||
} from "@earendil-works/pi-coding-agent";
|
} from "@earendil-works/pi-coding-agent";
|
||||||
import { customProviderRegistryKey, getEnabledPiExtensionPaths, getFusionAgentDir, getLegacyPiAgentDir, getProjectRootFromWorktree, reconcileClaudeCliPaths, reconcileDroidCliPaths, resolvePiExtensionProjectRoot } from "@fusion/core";
|
import {
|
||||||
|
customProviderRegistryKey,
|
||||||
|
getEnabledPiExtensionPaths,
|
||||||
|
getFusionAgentDir,
|
||||||
|
getLegacyPiAgentDir,
|
||||||
|
getProjectRootFromWorktree,
|
||||||
|
reconcileClaudeCliPaths,
|
||||||
|
reconcileDroidCliPaths,
|
||||||
|
resolvePiExtensionProjectRoot,
|
||||||
|
ZAI_PROVIDER_ID,
|
||||||
|
ZAI_PROVIDER_REGISTRATION,
|
||||||
|
} from "@fusion/core";
|
||||||
import type {
|
import type {
|
||||||
AgentPermissionPolicyActionCategory,
|
AgentPermissionPolicyActionCategory,
|
||||||
PermanentAgentActionCategory,
|
PermanentAgentActionCategory,
|
||||||
@@ -1353,6 +1364,13 @@ function resolveVendoredDroidCliEntry(): string | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function registerExtensionProviders(cwd: string, modelRegistry: ModelRegistry): Promise<void> {
|
async function registerExtensionProviders(cwd: string, modelRegistry: ModelRegistry): Promise<void> {
|
||||||
|
try {
|
||||||
|
modelRegistry.registerProvider(ZAI_PROVIDER_ID, ZAI_PROVIDER_REGISTRATION);
|
||||||
|
} catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
extensionsLog.warn(`Failed to register built-in ${ZAI_PROVIDER_ID} provider: ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const agentDir = getPackageManagerAgentDir();
|
const agentDir = getPackageManagerAgentDir();
|
||||||
const packageManager = new DefaultPackageManager({
|
const packageManager = new DefaultPackageManager({
|
||||||
|
|||||||
Reference in New Issue
Block a user