@kognitivedev/vercel-ai-provider 0.1.7 → 0.1.9
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.
- package/dist/__tests__/wrap-stream-logging.test.js +92 -0
- package/dist/index.d.ts +22 -1
- package/dist/index.js +333 -60
- package/package.json +1 -1
- package/src/__tests__/wrap-stream-logging.test.ts +104 -0
- package/src/index.ts +392 -64
|
@@ -36,6 +36,110 @@ describe("wrapStream logging", () => {
|
|
|
36
36
|
);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
+
it("should capture tool-call chunks and include them in logged conversation", 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: "Let me check" },
|
|
45
|
+
{ type: "text-end" as const, id: "t1" },
|
|
46
|
+
{
|
|
47
|
+
type: "tool-call" as const,
|
|
48
|
+
toolCallId: "call-1",
|
|
49
|
+
toolName: "get_weather",
|
|
50
|
+
input: '{"city":"London"}',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: "tool-result" as const,
|
|
54
|
+
toolCallId: "call-1",
|
|
55
|
+
toolName: "get_weather",
|
|
56
|
+
result: { temperature: 15, unit: "celsius" },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "finish" as const,
|
|
60
|
+
finishReason: {
|
|
61
|
+
unified: "tool-calls" as const,
|
|
62
|
+
raw: undefined,
|
|
63
|
+
},
|
|
64
|
+
usage: {
|
|
65
|
+
inputTokens: { total: 20, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
|
|
66
|
+
outputTokens: { total: 15, text: undefined, reasoning: undefined },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
] satisfies import("@ai-sdk/provider").LanguageModelV3StreamPart[]),
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const mockProvider = () => mockModel;
|
|
74
|
+
|
|
75
|
+
const cl = createCognitiveLayer({
|
|
76
|
+
provider: mockProvider,
|
|
77
|
+
clConfig: {
|
|
78
|
+
apiKey: "test-api-key",
|
|
79
|
+
appId: "test-app",
|
|
80
|
+
projectId: "test-project",
|
|
81
|
+
processDelayMs: 0,
|
|
82
|
+
logLevel: "none",
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const model = cl("mock-model", {
|
|
87
|
+
userId: "user-1",
|
|
88
|
+
projectId: "project-1",
|
|
89
|
+
sessionId: "session-1",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const result = streamText({
|
|
93
|
+
model,
|
|
94
|
+
messages: [{ role: "user", content: "What's the weather in London?" }],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Fully consume the stream
|
|
98
|
+
await result.text;
|
|
99
|
+
|
|
100
|
+
// Wait for async logConversation to complete
|
|
101
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
102
|
+
|
|
103
|
+
// Find the log call
|
|
104
|
+
const logCall = fetchCalls.find((c) => c.url.includes("/api/cognitive/log"));
|
|
105
|
+
expect(logCall).toBeDefined();
|
|
106
|
+
|
|
107
|
+
const messages = logCall!.body.messages;
|
|
108
|
+
|
|
109
|
+
// Assistant message should contain text + tool-call parts
|
|
110
|
+
const assistantMsg = messages.find((m: any) => m.role === "assistant");
|
|
111
|
+
expect(assistantMsg).toBeDefined();
|
|
112
|
+
expect(assistantMsg.content).toEqual([
|
|
113
|
+
{ type: "text", text: "Let me check" },
|
|
114
|
+
{
|
|
115
|
+
type: "tool-call",
|
|
116
|
+
toolCallId: "call-1",
|
|
117
|
+
toolName: "get_weather",
|
|
118
|
+
input: '{"city":"London"}',
|
|
119
|
+
},
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
// Tool results should be in a separate tool message
|
|
123
|
+
const toolMsg = messages.find((m: any) => m.role === "tool");
|
|
124
|
+
expect(toolMsg).toBeDefined();
|
|
125
|
+
expect(toolMsg.content).toEqual([
|
|
126
|
+
{
|
|
127
|
+
type: "tool-result",
|
|
128
|
+
toolCallId: "call-1",
|
|
129
|
+
toolName: "get_weather",
|
|
130
|
+
result: { temperature: 15, unit: "celsius" },
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
// Spans should include the tool call with populated previews
|
|
135
|
+
const spans = logCall!.body.spans;
|
|
136
|
+
const toolSpan = spans?.find((s: any) => s.spanType === "tool");
|
|
137
|
+
expect(toolSpan).toBeDefined();
|
|
138
|
+
expect(toolSpan.toolName).toBe("get_weather");
|
|
139
|
+
expect(toolSpan.inputPreview).toContain("London");
|
|
140
|
+
expect(toolSpan.outputPreview).toContain("15");
|
|
141
|
+
});
|
|
142
|
+
|
|
39
143
|
it("should include assistant message in logged conversation after streaming", async () => {
|
|
40
144
|
const mockModel = new MockLanguageModelV3({
|
|
41
145
|
doStream: async () => ({
|