fix: bound AI analysis provider latency
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { AiRuntimeConfigResult } from "@/modules/ai/server/config";
|
||||
import { getAiRuntimeConfig } from "@/modules/ai/server/config";
|
||||
import type { ElderAiResidentContext } from "@/modules/ai/server/elder-context";
|
||||
import { buildElderAiContext } from "@/modules/ai/server/elder-context";
|
||||
@@ -95,14 +94,17 @@ type ReturnlessMock = ReturnlessFunction & {
|
||||
|
||||
type ReturnlessFunction = (...args: unknown[]) => unknown;
|
||||
|
||||
const runtimeConfig: AiRuntimeConfigResult = {
|
||||
const runtimeConfig = {
|
||||
success: true,
|
||||
config: {
|
||||
baseUrl: "https://ai.example.test/v1",
|
||||
apiKey: "test-api-key",
|
||||
chatModel: "gpt-test",
|
||||
requestTimeoutMs: 12_345,
|
||||
maxTokens: 901,
|
||||
maxRetries: 4,
|
||||
},
|
||||
};
|
||||
} as const;
|
||||
|
||||
const account: AuthContext["account"] = {
|
||||
id: "account-1",
|
||||
@@ -327,6 +329,52 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe("elder AI analysis service", () => {
|
||||
it("constructs ChatOpenAI with latency controls from AI runtime config", async () => {
|
||||
const result = await generateElderAiAnalysis(createAuthContext(), "elder-1");
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(ChatOpenAI).toHaveBeenCalledWith(expect.objectContaining({
|
||||
apiKey: "test-api-key",
|
||||
model: "gpt-test",
|
||||
timeout: 12_345,
|
||||
maxTokens: 901,
|
||||
maxRetries: 4,
|
||||
configuration: { baseURL: "https://ai.example.test/v1" },
|
||||
}));
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "AbortError",
|
||||
error: Object.assign(new Error("aborted request with sk-live-secret and resident prompt"), { name: "AbortError" }),
|
||||
},
|
||||
{
|
||||
name: "timeout-like provider message",
|
||||
error: new Error("request timed out after 12345ms with sk-live-secret and resident prompt"),
|
||||
},
|
||||
])("maps $name model failures to sanitized timeout failed history", async ({ error }) => {
|
||||
const database = createDatabaseFake();
|
||||
useDatabase(database);
|
||||
chatMocks.invoke.mockRejectedValue(error);
|
||||
|
||||
const result = await generateElderAiAnalysis(createAuthContext(), "elder-1");
|
||||
|
||||
expect(result).toEqual({ success: false, reason: "AI 服务响应超时", status: 502 });
|
||||
expect(database.insertedValues).toEqual([
|
||||
expect.objectContaining({
|
||||
status: "failed",
|
||||
dataScopes: ["elder", "health"],
|
||||
errorCategory: "timeout",
|
||||
errorReason: "AI 服务响应超时",
|
||||
}),
|
||||
]);
|
||||
const persistedFailure = JSON.stringify(database.insertedValues[0]);
|
||||
expect(persistedFailure).not.toContain("sk-live-secret");
|
||||
expect(persistedFailure).not.toContain("resident prompt");
|
||||
expect(persistedFailure).not.toContain("Night wandering");
|
||||
expect(recordAuditLog).toHaveBeenCalledWith(expect.objectContaining({ result: "failure", reason: "AI 服务响应超时" }));
|
||||
});
|
||||
|
||||
it("saves sanitized failed history when AI runtime config is missing", async () => {
|
||||
const database = createDatabaseFake();
|
||||
useDatabase(database);
|
||||
|
||||
Reference in New Issue
Block a user