Agents: wire GigaChat compaction stream
This commit is contained in:
parent
1ae292ce26
commit
78593ccf84
@ -6,6 +6,7 @@ const {
|
||||
ensureRuntimePluginsLoaded,
|
||||
resolveContextEngineMock,
|
||||
resolveModelMock,
|
||||
ensureAuthProfileStoreMock,
|
||||
sessionCompactImpl,
|
||||
triggerInternalHook,
|
||||
sanitizeSessionHistoryMock,
|
||||
@ -15,6 +16,10 @@ const {
|
||||
resolveSessionAgentIdMock,
|
||||
estimateTokensMock,
|
||||
sessionAbortCompactionMock,
|
||||
createGigachatStreamFnMock,
|
||||
gigachatStreamFn,
|
||||
lastCreatedSession,
|
||||
lastInitialStreamFn,
|
||||
} = vi.hoisted(() => {
|
||||
const contextEngineCompactMock = vi.fn(async () => ({
|
||||
ok: true as boolean,
|
||||
@ -67,6 +72,10 @@ const {
|
||||
resolveSessionAgentIdMock: vi.fn(() => "main"),
|
||||
estimateTokensMock: vi.fn((_message?: unknown) => 10),
|
||||
sessionAbortCompactionMock: vi.fn(),
|
||||
createGigachatStreamFnMock: vi.fn(),
|
||||
gigachatStreamFn: vi.fn(),
|
||||
lastCreatedSession: { current: null as null | { agent: { streamFn: unknown } } },
|
||||
lastInitialStreamFn: { current: null as unknown },
|
||||
};
|
||||
});
|
||||
|
||||
@ -98,6 +107,7 @@ vi.mock("@mariozechner/pi-coding-agent", () => {
|
||||
AuthStorage: class AuthStorage {},
|
||||
ModelRegistry: class ModelRegistry {},
|
||||
createAgentSession: vi.fn(async () => {
|
||||
const initialStreamFn = vi.fn();
|
||||
const session = {
|
||||
sessionId: "session-1",
|
||||
messages: [
|
||||
@ -116,7 +126,7 @@ vi.mock("@mariozechner/pi-coding-agent", () => {
|
||||
replaceMessages: vi.fn((messages: unknown[]) => {
|
||||
session.messages = [...(messages as typeof session.messages)];
|
||||
}),
|
||||
streamFn: vi.fn(),
|
||||
streamFn: initialStreamFn,
|
||||
},
|
||||
compact: vi.fn(async () => {
|
||||
// simulate compaction trimming to a single message
|
||||
@ -126,6 +136,8 @@ vi.mock("@mariozechner/pi-coding-agent", () => {
|
||||
abortCompaction: sessionAbortCompactionMock,
|
||||
dispose: vi.fn(),
|
||||
};
|
||||
lastCreatedSession.current = session;
|
||||
lastInitialStreamFn.current = initialStreamFn;
|
||||
return { session };
|
||||
}),
|
||||
SessionManager: {
|
||||
@ -155,10 +167,15 @@ vi.mock("../models-config.js", () => ({
|
||||
|
||||
vi.mock("../model-auth.js", () => ({
|
||||
applyLocalNoAuthHeaderOverride: vi.fn((model: unknown) => model),
|
||||
ensureAuthProfileStore: ensureAuthProfileStoreMock,
|
||||
getApiKeyForModel: vi.fn(async () => ({ apiKey: "test", mode: "env" })),
|
||||
resolveModelAuthMode: vi.fn(() => "env"),
|
||||
}));
|
||||
|
||||
vi.mock("../gigachat-stream.js", () => ({
|
||||
createGigachatStreamFn: createGigachatStreamFnMock,
|
||||
}));
|
||||
|
||||
vi.mock("../sandbox.js", () => ({
|
||||
resolveSandboxContext: vi.fn(async () => null),
|
||||
}));
|
||||
@ -425,6 +442,12 @@ describe("compactEmbeddedPiSessionDirect hooks", () => {
|
||||
estimateTokensMock.mockReset();
|
||||
estimateTokensMock.mockReturnValue(10);
|
||||
sessionAbortCompactionMock.mockReset();
|
||||
ensureAuthProfileStoreMock.mockReset();
|
||||
ensureAuthProfileStoreMock.mockReturnValue({ profiles: {} });
|
||||
createGigachatStreamFnMock.mockReset();
|
||||
createGigachatStreamFnMock.mockReturnValue(gigachatStreamFn);
|
||||
lastCreatedSession.current = null;
|
||||
lastInitialStreamFn.current = null;
|
||||
unregisterApiProviders(getCustomApiRegistrySourceId("ollama"));
|
||||
});
|
||||
|
||||
@ -795,6 +818,62 @@ describe("compactEmbeddedPiSessionDirect hooks", () => {
|
||||
expect(result.reason).toContain("request timed out");
|
||||
expect(sessionAbortCompactionMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("installs the GigaChat stream for compaction-created sessions", async () => {
|
||||
resolveModelMock.mockReturnValue({
|
||||
model: {
|
||||
provider: "gigachat",
|
||||
api: "openai-completions",
|
||||
id: "GigaChat-2-Max",
|
||||
input: ["text"],
|
||||
baseUrl: "https://gigachat.devices.sberbank.ru/api/v1",
|
||||
},
|
||||
error: null,
|
||||
authStorage: { setRuntimeApiKey: vi.fn() },
|
||||
modelRegistry: {},
|
||||
} as never);
|
||||
ensureAuthProfileStoreMock.mockReturnValue({
|
||||
profiles: {
|
||||
"gigachat:business": {
|
||||
type: "api_key",
|
||||
metadata: {
|
||||
authMode: "basic",
|
||||
insecureTls: "true",
|
||||
scope: "GIGACHAT_API_PERS",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
sessionCompactImpl.mockImplementation(async () => {
|
||||
expect(createGigachatStreamFnMock).toHaveBeenCalledWith({
|
||||
baseUrl: "https://gigachat.devices.sberbank.ru/api/v1",
|
||||
authMode: "basic",
|
||||
insecureTls: true,
|
||||
scope: "GIGACHAT_API_PERS",
|
||||
});
|
||||
expect(lastCreatedSession.current?.agent.streamFn).toBe(gigachatStreamFn);
|
||||
expect(lastCreatedSession.current?.agent.streamFn).not.toBe(lastInitialStreamFn.current);
|
||||
return {
|
||||
summary: "summary",
|
||||
firstKeptEntryId: "entry-1",
|
||||
tokensBefore: 120,
|
||||
details: { ok: true },
|
||||
};
|
||||
});
|
||||
|
||||
const result = await compactEmbeddedPiSessionDirect({
|
||||
sessionId: "session-1",
|
||||
sessionKey: "agent:main:session-1",
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
workspaceDir: "/tmp",
|
||||
provider: "gigachat",
|
||||
model: "GigaChat-2-Max",
|
||||
authProfileId: "gigachat:business",
|
||||
customInstructions: "focus on decisions",
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("compactEmbeddedPiSession hooks (ownsCompaction engine)", () => {
|
||||
|
||||
@ -43,12 +43,15 @@ import { ensureCustomApiRegistered } from "../custom-api-registry.js";
|
||||
import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone } from "../date-time.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER } from "../defaults.js";
|
||||
import { resolveOpenClawDocsPath } from "../docs-path.js";
|
||||
import { createGigachatStreamFn } from "../gigachat-stream.js";
|
||||
import { resolveMemorySearchConfig } from "../memory-search.js";
|
||||
import {
|
||||
applyLocalNoAuthHeaderOverride,
|
||||
ensureAuthProfileStore,
|
||||
getApiKeyForModel,
|
||||
resolveModelAuthMode,
|
||||
} from "../model-auth.js";
|
||||
import { normalizeProviderId } from "../model-selection.js";
|
||||
import { supportsModelTools } from "../model-tool-support.js";
|
||||
import { ensureOpenClawModelsJson } from "../models-config.js";
|
||||
import { createConfiguredOllamaStreamFn } from "../ollama-stream.js";
|
||||
@ -794,6 +797,25 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
providerBaseUrl,
|
||||
}),
|
||||
);
|
||||
} else if (normalizeProviderId(provider) === "gigachat") {
|
||||
const providerConfig = params.config?.models?.providers?.[provider];
|
||||
const baseUrl =
|
||||
(typeof providerConfig?.baseUrl === "string" ? providerConfig.baseUrl : undefined) ??
|
||||
(typeof model.baseUrl === "string" ? model.baseUrl : undefined) ??
|
||||
process.env.GIGACHAT_BASE_URL?.trim() ??
|
||||
"https://gigachat.devices.sberbank.ru/api/v1";
|
||||
const gigachatStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
|
||||
const profileId = authProfileId?.trim() || "gigachat:default";
|
||||
const gigachatCred =
|
||||
gigachatStore.profiles[profileId] ?? gigachatStore.profiles["gigachat:default"];
|
||||
const gigachatMeta = gigachatCred?.type === "api_key" ? gigachatCred.metadata : undefined;
|
||||
|
||||
session.agent.streamFn = createGigachatStreamFn({
|
||||
baseUrl,
|
||||
authMode: (gigachatMeta?.authMode as "oauth" | "basic") ?? "oauth",
|
||||
insecureTls: gigachatMeta?.insecureTls === "true",
|
||||
scope: gigachatMeta?.scope,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user