@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.
package/README.md CHANGED
@@ -24,7 +24,7 @@ import { openai } from "@ai-sdk/openai";
24
24
  import { generateText } from "ai";
25
25
 
26
26
  // 1. Create the cognitive layer
27
- const clModel = createCognitiveLayer({
27
+ const cl = createCognitiveLayer({
28
28
  provider: openai,
29
29
  clConfig: {
30
30
  appId: "my-app",
@@ -35,7 +35,7 @@ const clModel = createCognitiveLayer({
35
35
 
36
36
  // 2. Use it with Vercel AI SDK
37
37
  const { text } = await generateText({
38
- model: clModel("gpt-4o", {
38
+ model: cl("gpt-4o", {
39
39
  userId: "user-123",
40
40
  sessionId: "session-abc"
41
41
  }),
@@ -49,17 +49,41 @@ const { text } = await generateText({
49
49
 
50
50
  | Option | Type | Required | Default | Description |
51
51
  |--------|------|----------|---------|-------------|
52
- | `appId` | `string` | | - | Unique identifier for your application |
52
+ | `appId` | `string` | Yes | - | Unique identifier for your application |
53
53
  | `defaultAgentId` | `string` | - | `"default"` | Default agent ID when not specified per-request |
54
54
  | `baseUrl` | `string` | - | `"http://localhost:3001"` | Kognitive backend API URL |
55
55
  | `apiKey` | `string` | - | - | API key for authentication (if required) |
56
56
  | `processDelayMs` | `number` | - | `500` | Delay before triggering memory processing (set to 0 to disable) |
57
+ | `logLevel` | `LogLevel` | - | `'info'` | Controls console logging verbosity |
58
+ | `providerFactory` | `(baseURL: string, apiKey: string) => (modelId: string) => LanguageModel` | - | - | Factory for creating a provider that routes through a gateway URL |
59
+
60
+ ### `LogLevel`
61
+
62
+ Controls verbosity of console output from the provider.
63
+
64
+ | Level | Description |
65
+ |-------|-------------|
66
+ | `'none'` | No logging |
67
+ | `'error'` | Only errors |
68
+ | `'warn'` | Errors and warnings |
69
+ | `'info'` | Errors, warnings, and info messages (default) |
70
+ | `'debug'` | All messages including detailed snapshot data |
71
+
72
+ ```typescript
73
+ const cl = createCognitiveLayer({
74
+ provider: openai,
75
+ clConfig: {
76
+ appId: "my-app",
77
+ logLevel: "debug" // see full snapshot data in console
78
+ }
79
+ });
80
+ ```
57
81
 
58
82
  ## API Reference
59
83
 
60
84
  ### `createCognitiveLayer(config)`
61
85
 
62
- Creates a model wrapper function that adds memory capabilities to any Vercel AI SDK provider.
86
+ Creates a cognitive layer that adds memory capabilities to any Vercel AI SDK provider.
63
87
 
64
88
  **Parameters:**
65
89
 
@@ -67,16 +91,34 @@ Creates a model wrapper function that adds memory capabilities to any Vercel AI
67
91
  createCognitiveLayer({
68
92
  provider: any, // Vercel AI SDK provider (e.g., openai, anthropic)
69
93
  clConfig: CognitiveLayerConfig
70
- }): CLModelWrapper
94
+ }): CognitiveLayer
71
95
  ```
72
96
 
73
- **Returns:** `CLModelWrapper` - A function to wrap models with memory capabilities.
97
+ **Returns:** `CognitiveLayer` - A callable model wrapper with `.streamText()` and `.generateText()` methods attached.
98
+
99
+ ---
100
+
101
+ ### `CognitiveLayer`
102
+
103
+ The return type of `createCognitiveLayer`. It is callable as a model wrapper and also exposes prompt-driven helpers.
104
+
105
+ ```typescript
106
+ type CognitiveLayer = CLModelWrapper & {
107
+ streamText: (options: CLStreamTextOptions) => Promise<ReturnType<typeof streamText>>;
108
+ generateText: (options: CLGenerateTextOptions) => ReturnType<typeof generateText>;
109
+ resolvePrompt: (slug: string) => Promise<CachedPrompt>;
110
+ logConversation: (payload: LogConversationPayload) => Promise<void>;
111
+ triggerProcessing: (userId: string, projectId: string, sessionId: string) => void;
112
+ clearPromptCache: () => void;
113
+ clearSessionCache: (sessionKey?: string) => void;
114
+ };
115
+ ```
74
116
 
75
117
  ---
76
118
 
77
119
  ### `CLModelWrapper`
78
120
 
79
- The function returned by `createCognitiveLayer`.
121
+ The callable signature of `CognitiveLayer`.
80
122
 
81
123
  ```typescript
82
124
  type CLModelWrapper = (
@@ -87,19 +129,32 @@ type CLModelWrapper = (
87
129
  sessionId?: string;
88
130
  },
89
131
  providerOptions?: Record<string, unknown>
90
- ) => LanguageModelV2;
132
+ ) => LanguageModel;
91
133
  ```
92
134
 
93
135
  **Parameters:**
94
136
 
95
137
  | Parameter | Type | Required | Description |
96
138
  |-----------|------|----------|-------------|
97
- | `modelId` | `string` | | Model identifier (e.g., `"gpt-4o"`, `"claude-3-opus"`) |
139
+ | `modelId` | `string` | Yes | Model identifier (e.g., `"gpt-4o"`, `"claude-3-opus"`) |
98
140
  | `settings.userId` | `string` | - | User identifier (required for memory features) |
99
141
  | `settings.agentId` | `string` | - | Override default agent ID |
100
142
  | `settings.sessionId` | `string` | - | Session identifier (required for logging) |
101
143
  | `providerOptions` | `Record<string, unknown>` | - | Provider-specific options passed directly to the underlying provider |
102
144
 
145
+ ---
146
+
147
+ ### `PromptConfig`
148
+
149
+ Used with `cl.streamText()` and `cl.generateText()` to reference a managed prompt.
150
+
151
+ ```typescript
152
+ interface PromptConfig {
153
+ slug: string;
154
+ variables?: Record<string, string>;
155
+ }
156
+ ```
157
+
103
158
  ## Usage Examples
104
159
 
105
160
  ### With OpenAI
@@ -109,7 +164,7 @@ import { createCognitiveLayer } from "@kognitivedev/vercel-ai-provider";
109
164
  import { openai } from "@ai-sdk/openai";
110
165
  import { generateText } from "ai";
111
166
 
112
- const clModel = createCognitiveLayer({
167
+ const cl = createCognitiveLayer({
113
168
  provider: openai,
114
169
  clConfig: {
115
170
  appId: "my-app",
@@ -118,7 +173,7 @@ const clModel = createCognitiveLayer({
118
173
  });
119
174
 
120
175
  const { text } = await generateText({
121
- model: clModel("gpt-4o", {
176
+ model: cl("gpt-4o", {
122
177
  userId: "user-123",
123
178
  sessionId: "session-abc"
124
179
  }),
@@ -139,7 +194,7 @@ const openrouter = createOpenRouter({
139
194
  apiKey: process.env.OPENROUTER_API_KEY
140
195
  });
141
196
 
142
- const clModel = createCognitiveLayer({
197
+ const cl = createCognitiveLayer({
143
198
  provider: openrouter.chat,
144
199
  clConfig: {
145
200
  appId: "my-app",
@@ -149,7 +204,7 @@ const clModel = createCognitiveLayer({
149
204
 
150
205
  // Pass provider-specific options as the third parameter
151
206
  const { text } = await generateText({
152
- model: clModel("moonshotai/kimi-k2-0905", {
207
+ model: cl("moonshotai/kimi-k2-0905", {
153
208
  userId: "user-123",
154
209
  sessionId: "session-abc"
155
210
  }, {
@@ -168,7 +223,7 @@ import { createCognitiveLayer } from "@kognitivedev/vercel-ai-provider";
168
223
  import { anthropic } from "@ai-sdk/anthropic";
169
224
  import { streamText } from "ai";
170
225
 
171
- const clModel = createCognitiveLayer({
226
+ const cl = createCognitiveLayer({
172
227
  provider: anthropic,
173
228
  clConfig: {
174
229
  appId: "my-app",
@@ -177,7 +232,7 @@ const clModel = createCognitiveLayer({
177
232
  });
178
233
 
179
234
  const result = await streamText({
180
- model: clModel("claude-3-5-sonnet-latest", {
235
+ model: cl("claude-3-5-sonnet-latest", {
181
236
  userId: "user-456",
182
237
  sessionId: "chat-xyz"
183
238
  }),
@@ -195,7 +250,7 @@ The provider automatically injects memory context into your system prompts:
195
250
 
196
251
  ```typescript
197
252
  const { text } = await generateText({
198
- model: clModel("gpt-4o", {
253
+ model: cl("gpt-4o", {
199
254
  userId: "user-123",
200
255
  sessionId: "session-abc"
201
256
  }),
@@ -206,13 +261,175 @@ const { text } = await generateText({
206
261
  // Memory context is automatically appended to system prompt
207
262
  ```
208
263
 
264
+ ### Prompt Management
265
+
266
+ Use `cl.streamText()` and `cl.generateText()` to resolve prompts by slug from the backend. Prompts are fetched from the `/api/cognitive/prompt` endpoint and cached for 60 seconds.
267
+
268
+ Template variables use `{{variable}}` syntax and are interpolated before the prompt is sent to the model.
269
+
270
+ ```typescript
271
+ // Stream with a managed prompt
272
+ const result = await cl.streamText({
273
+ model: cl("gpt-4o", {
274
+ userId: "user-123",
275
+ sessionId: "session-abc"
276
+ }),
277
+ prompt: {
278
+ slug: "customer-support",
279
+ variables: {
280
+ companyName: "Acme Corp",
281
+ language: "English"
282
+ }
283
+ },
284
+ messages: [{ role: "user", content: "I need help with my order" }]
285
+ });
286
+
287
+ for await (const chunk of result.textStream) {
288
+ process.stdout.write(chunk);
289
+ }
290
+ ```
291
+
292
+ ```typescript
293
+ // Generate with a managed prompt
294
+ const { text } = await cl.generateText({
295
+ model: cl("gpt-4o", {
296
+ userId: "user-123",
297
+ sessionId: "session-abc"
298
+ }),
299
+ prompt: {
300
+ slug: "summarizer"
301
+ },
302
+ messages: [{ role: "user", content: "Summarize this document..." }]
303
+ });
304
+ ```
305
+
306
+ ### Gateway Routing
307
+
308
+ When a prompt has a `gatewaySlug` configured on the backend, requests are automatically routed through the gateway endpoint at `{baseUrl}/api/cognitive/gateway/{gatewaySlug}`.
309
+
310
+ To enable gateway routing, provide a `providerFactory` in your config:
311
+
312
+ ```typescript
313
+ import { createOpenAI } from "@ai-sdk/openai";
314
+
315
+ const cl = createCognitiveLayer({
316
+ provider: openai,
317
+ clConfig: {
318
+ appId: "my-app",
319
+ baseUrl: "https://api.kognitive.dev",
320
+ providerFactory: (baseURL, apiKey) => {
321
+ const gatewayProvider = createOpenAI({ baseURL, apiKey });
322
+ return (modelId) => gatewayProvider(modelId);
323
+ }
324
+ }
325
+ });
326
+ ```
327
+
328
+ Without `providerFactory`, the provider will log a warning and skip gateway routing, sending requests directly to the original provider.
329
+
330
+ ### `cl.resolvePrompt(slug)`
331
+
332
+ Fetches and caches a prompt by slug from the backend. Prompts are cached for 60 seconds.
333
+
334
+ ```typescript
335
+ const prompt = await cl.resolvePrompt("customer-support");
336
+ console.log(prompt.content); // The prompt template text
337
+ console.log(prompt.version); // Prompt version number
338
+ console.log(prompt.promptId); // Unique prompt ID
339
+ ```
340
+
341
+ **Returns:** `Promise<CachedPrompt>`
342
+
343
+ ```typescript
344
+ interface CachedPrompt {
345
+ promptId: string;
346
+ slug: string;
347
+ version: number;
348
+ content: string;
349
+ fetchedAt: number;
350
+ gatewaySlug?: string;
351
+ }
352
+ ```
353
+
354
+ ---
355
+
356
+ ### `cl.logConversation(payload)`
357
+
358
+ Manually logs a conversation to the backend for memory processing.
359
+
360
+ ```typescript
361
+ await cl.logConversation({
362
+ userId: "user-123",
363
+ projectId: "my-project",
364
+ sessionId: "session-abc",
365
+ messages: [
366
+ { role: "user", content: "Hello" },
367
+ { role: "assistant", content: "Hi there!" }
368
+ ],
369
+ modelId: "gpt-4o",
370
+ });
371
+ ```
372
+
373
+ **Parameters:** `LogConversationPayload`
374
+
375
+ ```typescript
376
+ interface LogConversationPayload {
377
+ userId: string;
378
+ projectId: string;
379
+ sessionId: string;
380
+ messages: any[];
381
+ memorySystemPrompt?: string;
382
+ modelId?: string;
383
+ usage?: Record<string, unknown>;
384
+ promptSlug?: string;
385
+ promptVersion?: number;
386
+ promptId?: string;
387
+ }
388
+ ```
389
+
390
+ ---
391
+
392
+ ### `cl.triggerProcessing(userId, projectId, sessionId)`
393
+
394
+ Manually triggers memory processing for a given session. This is normally called automatically after logging, but can be invoked independently.
395
+
396
+ ```typescript
397
+ cl.triggerProcessing("user-123", "my-project", "session-abc");
398
+ ```
399
+
400
+ ---
401
+
402
+ ### `cl.clearPromptCache()`
403
+
404
+ Clears all cached prompts, forcing the next `resolvePrompt` call to fetch fresh data from the backend.
405
+
406
+ ```typescript
407
+ cl.clearPromptCache();
408
+ ```
409
+
410
+ ---
411
+
412
+ ### `cl.clearSessionCache(sessionKey?)`
413
+
414
+ Clears cached memory snapshots. Pass a specific session key (`"userId:projectId:sessionId"`) to clear one session, or omit to clear all.
415
+
416
+ ```typescript
417
+ // Clear a specific session
418
+ cl.clearSessionCache("user-123:my-project:session-abc");
419
+
420
+ // Clear all cached sessions
421
+ cl.clearSessionCache();
422
+ ```
423
+
424
+ ---
425
+
209
426
  ### Without Memory (Anonymous Users)
210
427
 
211
428
  Skip memory features by omitting `userId`:
212
429
 
213
430
  ```typescript
214
431
  const { text } = await generateText({
215
- model: clModel("gpt-4o"),
432
+ model: cl("gpt-4o"),
216
433
  prompt: "General question without memory"
217
434
  });
218
435
  ```
@@ -258,6 +475,8 @@ The provider communicates with your Kognitive backend via these endpoints:
258
475
  | `/api/cognitive/snapshot` | GET | Fetches user's memory snapshot |
259
476
  | `/api/cognitive/log` | POST | Logs conversation for processing |
260
477
  | `/api/cognitive/process` | POST | Triggers memory extraction/management |
478
+ | `/api/cognitive/prompt` | GET | Resolves a managed prompt by slug |
479
+ | `/api/cognitive/gateway/{slug}` | * | Gateway proxy endpoint for routed requests |
261
480
 
262
481
  ### Query Parameters for Snapshot
263
482
 
@@ -292,6 +511,14 @@ clConfig: {
292
511
  }
293
512
  ```
294
513
 
514
+ ### Gateway not routing
515
+
516
+ If requests are not being routed through the gateway:
517
+
518
+ 1. Ensure `providerFactory` is set in your `clConfig`
519
+ 2. Verify the prompt has a `gatewaySlug` configured on the backend
520
+ 3. Set `logLevel: 'debug'` to inspect gateway resolution logs
521
+
295
522
  ## License
296
523
 
297
524
  MIT
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const index_1 = require("../index");
5
+ const ai_1 = require("ai");
6
+ const test_1 = require("ai/test");
7
+ (0, vitest_1.describe)("wrapStream logging", () => {
8
+ let fetchCalls;
9
+ (0, vitest_1.beforeEach)(() => {
10
+ fetchCalls = [];
11
+ vitest_1.vi.stubGlobal("fetch", vitest_1.vi.fn(async (url, init) => {
12
+ const urlStr = typeof url === "string" ? url : url.toString();
13
+ if (urlStr.includes("/api/cognitive/snapshot")) {
14
+ return new Response(JSON.stringify({ systemBlock: "", userContextBlock: "" }), { status: 200, headers: { "Content-Type": "application/json" } });
15
+ }
16
+ if (urlStr.includes("/api/cognitive/log")) {
17
+ const body = JSON.parse(init === null || init === void 0 ? void 0 : init.body);
18
+ fetchCalls.push({ url: urlStr, body });
19
+ return new Response(JSON.stringify({ ok: true }), { status: 200 });
20
+ }
21
+ if (urlStr.includes("/api/cognitive/process")) {
22
+ return new Response(JSON.stringify({ ok: true }), { status: 200 });
23
+ }
24
+ return new Response("not found", { status: 404 });
25
+ }));
26
+ });
27
+ (0, vitest_1.it)("should include assistant message in logged conversation after streaming", async () => {
28
+ const mockModel = new test_1.MockLanguageModelV3({
29
+ doStream: async () => ({
30
+ stream: (0, test_1.convertArrayToReadableStream)([
31
+ { type: "text-start", id: "t1" },
32
+ { type: "text-delta", id: "t1", delta: "Hello" },
33
+ { type: "text-delta", id: "t1", delta: " world" },
34
+ { type: "text-end", id: "t1" },
35
+ {
36
+ type: "finish",
37
+ finishReason: {
38
+ unified: "stop",
39
+ raw: undefined,
40
+ },
41
+ usage: {
42
+ inputTokens: { total: 10, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
43
+ outputTokens: { total: 5, text: undefined, reasoning: undefined },
44
+ },
45
+ },
46
+ ]),
47
+ }),
48
+ });
49
+ const mockProvider = () => mockModel;
50
+ const cl = (0, index_1.createCognitiveLayer)({
51
+ provider: mockProvider,
52
+ clConfig: {
53
+ apiKey: "test-api-key",
54
+ appId: "test-app",
55
+ projectId: "test-project",
56
+ processDelayMs: 0,
57
+ logLevel: "none",
58
+ },
59
+ });
60
+ const model = cl("mock-model", {
61
+ userId: "user-1",
62
+ projectId: "project-1",
63
+ sessionId: "session-1",
64
+ });
65
+ const result = (0, ai_1.streamText)({
66
+ model,
67
+ messages: [{ role: "user", content: "Hi" }],
68
+ });
69
+ // Fully consume the stream
70
+ const text = await result.text;
71
+ (0, vitest_1.expect)(text).toBe("Hello world");
72
+ // Wait for async logConversation to complete
73
+ await new Promise((r) => setTimeout(r, 100));
74
+ // Find the log call
75
+ const logCall = fetchCalls.find((c) => c.url.includes("/api/cognitive/log"));
76
+ (0, vitest_1.expect)(logCall).toBeDefined();
77
+ const messages = logCall.body.messages;
78
+ const assistantMsg = messages.find((m) => m.role === "assistant");
79
+ (0, vitest_1.expect)(assistantMsg).toBeDefined();
80
+ (0, vitest_1.expect)(assistantMsg.content).toEqual([
81
+ { type: "text", text: "Hello world" },
82
+ ]);
83
+ });
84
+ });
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { LanguageModelV2 } from "@ai-sdk/provider";
1
+ import { streamText as aiStreamText, generateText as aiGenerateText, type LanguageModel } from "ai";
2
2
  /**
3
3
  * Log levels for controlling verbosity of CognitiveLayer logging.
4
4
  * - 'none': No logging
@@ -9,10 +9,10 @@ import { LanguageModelV2 } from "@ai-sdk/provider";
9
9
  */
10
10
  export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
11
11
  export interface CognitiveLayerConfig {
12
- appId: string;
13
- defaultAgentId?: string;
12
+ apiKey: string;
13
+ appId?: string;
14
+ projectId?: string;
14
15
  baseUrl?: string;
15
- apiKey?: string;
16
16
  /**
17
17
  * Delay in milliseconds before triggering memory processing after a response.
18
18
  * Set to 0 to disable automatic processing.
@@ -21,21 +21,59 @@ export interface CognitiveLayerConfig {
21
21
  processDelayMs?: number;
22
22
  /**
23
23
  * Log level for controlling verbosity of CognitiveLayer logging.
24
- * - 'none': No logging
25
- * - 'error': Only errors
26
- * - 'warn': Errors and warnings
27
- * - 'info': Errors, warnings, and info messages
28
- * - 'debug': All messages including detailed snapshot data
29
24
  * Default: 'info'
30
25
  */
31
26
  logLevel?: LogLevel;
27
+ /**
28
+ * Factory for creating a provider that routes through a gateway URL.
29
+ */
30
+ providerFactory?: (baseURL: string, apiKey: string) => (modelId: string) => LanguageModel;
32
31
  }
33
32
  export type CLModelWrapper = (modelId: string, settings?: {
34
33
  userId?: string;
35
- agentId?: string;
34
+ projectId?: string;
36
35
  sessionId?: string;
37
- }, providerOptions?: Record<string, unknown>) => LanguageModelV2;
36
+ }, providerOptions?: Record<string, unknown>) => LanguageModel;
37
+ export interface PromptConfig {
38
+ slug: string;
39
+ variables?: Record<string, string>;
40
+ }
41
+ export type CLStreamTextOptions = Omit<Parameters<typeof aiStreamText>[0], 'system' | 'prompt'> & {
42
+ prompt: PromptConfig;
43
+ };
44
+ export type CLGenerateTextOptions = Omit<Parameters<typeof aiGenerateText>[0], 'system' | 'prompt'> & {
45
+ prompt: PromptConfig;
46
+ };
47
+ export interface LogConversationPayload {
48
+ userId: string;
49
+ projectId: string;
50
+ sessionId: string;
51
+ messages: any[];
52
+ memorySystemPrompt?: string;
53
+ modelId?: string;
54
+ usage?: Record<string, unknown>;
55
+ promptSlug?: string;
56
+ promptVersion?: number;
57
+ promptId?: string;
58
+ }
59
+ export type CognitiveLayer = CLModelWrapper & {
60
+ streamText: (options: CLStreamTextOptions) => Promise<ReturnType<typeof aiStreamText>>;
61
+ generateText: (options: CLGenerateTextOptions) => ReturnType<typeof aiGenerateText>;
62
+ resolvePrompt: (slug: string) => Promise<CachedPrompt>;
63
+ logConversation: (payload: LogConversationPayload) => Promise<void>;
64
+ triggerProcessing: (userId: string, projectId: string, sessionId: string) => void;
65
+ clearPromptCache: () => void;
66
+ clearSessionCache: (sessionKey?: string) => void;
67
+ };
68
+ export interface CachedPrompt {
69
+ promptId: string;
70
+ slug: string;
71
+ version: number;
72
+ content: string;
73
+ fetchedAt: number;
74
+ gatewaySlug?: string;
75
+ }
38
76
  export declare function createCognitiveLayer(config: {
39
77
  provider: any;
40
78
  clConfig: CognitiveLayerConfig;
41
- }): CLModelWrapper;
79
+ }): CognitiveLayer;