@kognitivedev/vercel-ai-provider 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,104 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { createCognitiveLayer } from "../index";
3
+ import { streamText } from "ai";
4
+ import { MockLanguageModelV3, convertArrayToReadableStream } from "ai/test";
5
+
6
+ describe("wrapStream logging", () => {
7
+ let fetchCalls: { url: string; body: any }[];
8
+
9
+ beforeEach(() => {
10
+ fetchCalls = [];
11
+
12
+ vi.stubGlobal(
13
+ "fetch",
14
+ vi.fn(async (url: string | URL | Request, init?: RequestInit) => {
15
+ const urlStr = typeof url === "string" ? url : url.toString();
16
+
17
+ if (urlStr.includes("/api/cognitive/snapshot")) {
18
+ return new Response(
19
+ JSON.stringify({ systemBlock: "", userContextBlock: "" }),
20
+ { status: 200, headers: { "Content-Type": "application/json" } }
21
+ );
22
+ }
23
+
24
+ if (urlStr.includes("/api/cognitive/log")) {
25
+ const body = JSON.parse(init?.body as string);
26
+ fetchCalls.push({ url: urlStr, body });
27
+ return new Response(JSON.stringify({ ok: true }), { status: 200 });
28
+ }
29
+
30
+ if (urlStr.includes("/api/cognitive/process")) {
31
+ return new Response(JSON.stringify({ ok: true }), { status: 200 });
32
+ }
33
+
34
+ return new Response("not found", { status: 404 });
35
+ })
36
+ );
37
+ });
38
+
39
+ it("should include assistant message in logged conversation after streaming", async () => {
40
+ const mockModel = new MockLanguageModelV3({
41
+ doStream: async () => ({
42
+ stream: convertArrayToReadableStream([
43
+ { type: "text-start" as const, id: "t1" },
44
+ { type: "text-delta" as const, id: "t1", delta: "Hello" },
45
+ { type: "text-delta" as const, id: "t1", delta: " world" },
46
+ { type: "text-end" as const, id: "t1" },
47
+ {
48
+ type: "finish" as const,
49
+ finishReason: {
50
+ unified: "stop" as const,
51
+ raw: undefined,
52
+ },
53
+ usage: {
54
+ inputTokens: { total: 10, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
55
+ outputTokens: { total: 5, text: undefined, reasoning: undefined },
56
+ },
57
+ },
58
+ ] satisfies import("@ai-sdk/provider").LanguageModelV3StreamPart[]),
59
+ }),
60
+ });
61
+
62
+ const mockProvider = () => mockModel;
63
+
64
+ const cl = createCognitiveLayer({
65
+ provider: mockProvider,
66
+ clConfig: {
67
+ apiKey: "test-api-key",
68
+ appId: "test-app",
69
+ projectId: "test-project",
70
+ processDelayMs: 0,
71
+ logLevel: "none",
72
+ },
73
+ });
74
+
75
+ const model = cl("mock-model", {
76
+ userId: "user-1",
77
+ projectId: "project-1",
78
+ sessionId: "session-1",
79
+ });
80
+
81
+ const result = streamText({
82
+ model,
83
+ messages: [{ role: "user", content: "Hi" }],
84
+ });
85
+
86
+ // Fully consume the stream
87
+ const text = await result.text;
88
+ expect(text).toBe("Hello world");
89
+
90
+ // Wait for async logConversation to complete
91
+ await new Promise((r) => setTimeout(r, 100));
92
+
93
+ // Find the log call
94
+ const logCall = fetchCalls.find((c) => c.url.includes("/api/cognitive/log"));
95
+ expect(logCall).toBeDefined();
96
+
97
+ const messages = logCall!.body.messages;
98
+ const assistantMsg = messages.find((m: any) => m.role === "assistant");
99
+ expect(assistantMsg).toBeDefined();
100
+ expect(assistantMsg.content).toEqual([
101
+ { type: "text", text: "Hello world" },
102
+ ]);
103
+ });
104
+ });