@krutai/ai-provider 0.1.0 → 0.2.1
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/AI_REFERENCE.md +51 -62
- package/README.md +88 -99
- package/dist/index.d.mts +106 -80
- package/dist/index.d.ts +106 -80
- package/dist/index.js +168 -123
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +166 -121
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/AI_REFERENCE.md
CHANGED
|
@@ -3,54 +3,64 @@
|
|
|
3
3
|
## Package Overview
|
|
4
4
|
|
|
5
5
|
- **Name**: `@krutai/ai-provider`
|
|
6
|
-
- **Version**: `0.
|
|
7
|
-
- **Purpose**: AI provider for KrutAI —
|
|
6
|
+
- **Version**: `0.2.0`
|
|
7
|
+
- **Purpose**: AI provider for KrutAI — fetch-based client for your deployed LangChain server with API key validation
|
|
8
8
|
- **Entry**: `src/index.ts` → `dist/index.{js,mjs,d.ts}`
|
|
9
|
-
- **Build**: `tsup` (CJS + ESM,
|
|
9
|
+
- **Build**: `tsup` (CJS + ESM, no external SDK deps)
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Architecture
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
@krutai/ai-provider@0.
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
@krutai/ai-provider@0.2.0
|
|
15
|
+
└── peerDep: krutai (core utilities)
|
|
16
|
+
|
|
17
|
+
AI Flow:
|
|
18
|
+
User App → krutAI() / KrutAIProvider
|
|
19
|
+
→ POST {serverUrl}/validate (key validation)
|
|
20
|
+
→ POST {serverUrl}/generate (single response)
|
|
21
|
+
→ POST {serverUrl}/stream (SSE streaming)
|
|
22
|
+
→ POST {serverUrl}/chat (multi-turn)
|
|
23
|
+
→ Your deployed LangChain server
|
|
17
24
|
```
|
|
18
25
|
|
|
19
|
-
> **Important for AI**: Do NOT bundle `@openrouter/sdk` inline. It must stay external in tsup.
|
|
20
|
-
|
|
21
26
|
## File Structure
|
|
22
27
|
|
|
23
28
|
```
|
|
24
29
|
packages/ai-provider/
|
|
25
30
|
├── src/
|
|
26
31
|
│ ├── index.ts # krutAI() factory + all exports
|
|
27
|
-
│ ├── client.ts # KrutAIProvider class
|
|
32
|
+
│ ├── client.ts # KrutAIProvider class (fetch-based)
|
|
28
33
|
│ ├── types.ts # KrutAIProviderConfig, GenerateOptions, ChatMessage, DEFAULT_MODEL
|
|
29
|
-
│ └── validator.ts #
|
|
34
|
+
│ └── validator.ts # API key format check + server validation
|
|
30
35
|
├── package.json
|
|
31
36
|
├── tsconfig.json
|
|
32
37
|
└── tsup.config.ts
|
|
33
38
|
```
|
|
34
39
|
|
|
35
|
-
##
|
|
40
|
+
## Server Endpoints (Expected by This Package)
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
| Endpoint | Method | Body | Response |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| `/validate` | POST | `{ apiKey }` | `{ valid: true/false, message? }` |
|
|
45
|
+
| `/generate` | POST | `{ prompt, model, system?, maxTokens?, temperature? }` | `{ text/content/message: string }` |
|
|
46
|
+
| `/stream` | POST | `{ prompt, model, system?, maxTokens?, temperature? }` | SSE stream `data: <chunk>` |
|
|
47
|
+
| `/chat` | POST | `{ messages, model, maxTokens?, temperature? }` | `{ text/content/message: string }` |
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
All AI endpoints receive `Authorization: Bearer <apiKey>` and `x-api-key: <apiKey>` headers.
|
|
42
50
|
|
|
43
51
|
## Main Exports
|
|
44
52
|
|
|
45
|
-
### `krutAI(config
|
|
46
|
-
|
|
47
|
-
Drop-in factory. Mirrors `krutAuth` from `@krutai/auth`.
|
|
53
|
+
### `krutAI(config)` ← PRIMARY API
|
|
48
54
|
|
|
49
55
|
```typescript
|
|
50
56
|
import { krutAI } from '@krutai/ai-provider';
|
|
51
57
|
|
|
52
|
-
const ai = krutAI(
|
|
53
|
-
|
|
58
|
+
const ai = krutAI({
|
|
59
|
+
apiKey: process.env.KRUTAI_API_KEY!,
|
|
60
|
+
serverUrl: 'https://ai.yourapp.com',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await ai.initialize(); // validates key with server
|
|
54
64
|
|
|
55
65
|
const text = await ai.generate('Hello!');
|
|
56
66
|
```
|
|
@@ -62,51 +72,32 @@ import { KrutAIProvider } from '@krutai/ai-provider';
|
|
|
62
72
|
|
|
63
73
|
const ai = new KrutAIProvider({
|
|
64
74
|
apiKey: process.env.KRUTAI_API_KEY!,
|
|
65
|
-
|
|
66
|
-
model: '
|
|
67
|
-
validateOnInit: true,
|
|
68
|
-
validationEndpoint: undefined, // TODO: wire up POST route
|
|
75
|
+
serverUrl: 'https://ai.yourapp.com',
|
|
76
|
+
model: 'gpt-4o', // optional, default: 'default'
|
|
77
|
+
validateOnInit: true, // default: true
|
|
69
78
|
});
|
|
70
79
|
|
|
71
80
|
await ai.initialize();
|
|
72
81
|
```
|
|
73
82
|
|
|
74
83
|
**Methods:**
|
|
75
|
-
- `initialize(): Promise<void>` — validates key
|
|
84
|
+
- `initialize(): Promise<void>` — validates key against server, marks provider ready
|
|
76
85
|
- `generate(prompt, opts?): Promise<string>` — single response (non-streaming)
|
|
77
|
-
- `stream(prompt, opts?)` —
|
|
86
|
+
- `stream(prompt, opts?)` — `AsyncGenerator<string>` — SSE-based streaming
|
|
78
87
|
- `chat(messages, opts?): Promise<string>` — multi-turn conversation
|
|
79
88
|
- `getModel(): string` — active model name
|
|
80
|
-
- `getClient(): OpenRouter` — raw `@openrouter/sdk` client (advanced)
|
|
81
89
|
- `isInitialized(): boolean`
|
|
82
90
|
|
|
83
|
-
## Underlying SDK Call
|
|
84
|
-
|
|
85
|
-
The package calls `@openrouter/sdk` using the following structure:
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// Non-streaming
|
|
89
|
-
client.chat.send({
|
|
90
|
-
chatGenerationParams: { model, messages, stream: false, maxTokens?, temperature? }
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Streaming
|
|
94
|
-
client.chat.send({
|
|
95
|
-
chatGenerationParams: { model, messages, stream: true, maxTokens?, temperature? }
|
|
96
|
-
});
|
|
97
|
-
```
|
|
98
|
-
|
|
99
91
|
## Types
|
|
100
92
|
|
|
101
93
|
### `KrutAIProviderConfig`
|
|
102
94
|
|
|
103
95
|
```typescript
|
|
104
96
|
interface KrutAIProviderConfig {
|
|
105
|
-
apiKey: string;
|
|
106
|
-
|
|
107
|
-
model?: string;
|
|
108
|
-
validateOnInit?: boolean;
|
|
109
|
-
validationEndpoint?: string; // POST URL for key validation (future)
|
|
97
|
+
apiKey: string; // KrutAI API key — validated with server (required)
|
|
98
|
+
serverUrl: string; // Base URL of deployed LangChain server (required)
|
|
99
|
+
model?: string; // default: 'default'
|
|
100
|
+
validateOnInit?: boolean; // default: true
|
|
110
101
|
}
|
|
111
102
|
```
|
|
112
103
|
|
|
@@ -132,29 +123,29 @@ interface GenerateOptions {
|
|
|
132
123
|
|
|
133
124
|
## Validator
|
|
134
125
|
|
|
135
|
-
Defined in `src/validator.ts
|
|
126
|
+
Defined in `src/validator.ts`.
|
|
136
127
|
|
|
137
128
|
```typescript
|
|
138
|
-
export {
|
|
129
|
+
export { validateApiKey, validateApiKeyFormat, KrutAIKeyValidationError };
|
|
139
130
|
```
|
|
140
131
|
|
|
141
132
|
### Validation Flow
|
|
142
133
|
|
|
143
|
-
1. **Format check** (sync, on construction): key must
|
|
144
|
-
2. **
|
|
134
|
+
1. **Format check** (sync, on construction): key must be a non-empty string
|
|
135
|
+
2. **Server check** (async, on `initialize()`): sends `POST {serverUrl}/validate` with the key; expects `{ valid: true }`
|
|
145
136
|
|
|
146
137
|
## tsup Configuration Notes
|
|
147
138
|
|
|
148
|
-
-
|
|
149
|
-
-
|
|
139
|
+
- Only `krutai` is external (peer dep, NOT bundled)
|
|
140
|
+
- No third-party AI SDK — pure native `fetch`
|
|
150
141
|
|
|
151
142
|
## Important Notes
|
|
152
143
|
|
|
153
|
-
1. **`
|
|
154
|
-
2.
|
|
155
|
-
3. **
|
|
156
|
-
4. **
|
|
157
|
-
5. **
|
|
144
|
+
1. **`serverUrl` is required** — point it at your deployed LangChain backend
|
|
145
|
+
2. **`apiKey` is validated server-side** — the server controls what keys are valid
|
|
146
|
+
3. **Streaming uses SSE** — server must respond with `Content-Type: text/event-stream`
|
|
147
|
+
4. **No external SDK needed** — uses native `fetch` only (Node 18+, browser, edge runtimes)
|
|
148
|
+
5. **Response field fallback** — tries `text → content → message` from server JSON response
|
|
158
149
|
|
|
159
150
|
## Related Packages
|
|
160
151
|
|
|
@@ -164,7 +155,5 @@ export { validateOpenRouterKeyFormat, validateOpenRouterKeyWithService, OpenRout
|
|
|
164
155
|
|
|
165
156
|
## Links
|
|
166
157
|
|
|
167
|
-
- OpenRouter SDK Docs: https://openrouter.ai/docs/sdks/typescript
|
|
168
|
-
- OpenRouter Models: https://openrouter.ai/models
|
|
169
158
|
- GitHub: https://github.com/AccountantAIOrg/krut_packages
|
|
170
159
|
- npm: https://www.npmjs.com/package/@krutai/ai-provider
|
package/README.md
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# @krutai/ai-provider
|
|
2
2
|
|
|
3
|
-
AI
|
|
3
|
+
AI provider package for KrutAI — fetch-based client for your deployed LangChain server.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
|
|
13
|
-
---
|
|
7
|
+
- 🔑 **API Key validation** — validates your key against the server before use
|
|
8
|
+
- 🚀 **Zero SDK dependencies** — uses native `fetch` only
|
|
9
|
+
- 📡 **Streaming** — SSE-based streaming via async generator
|
|
10
|
+
- 💬 **Multi-turn chat** — full conversation history support
|
|
11
|
+
- ⚙️ **Configurable** — pass any model name to the server
|
|
14
12
|
|
|
15
13
|
## Installation
|
|
16
14
|
|
|
@@ -18,146 +16,137 @@ AI Provider package for KrutAI — a thin wrapper around [`@openrouter/sdk`](htt
|
|
|
18
16
|
npm install @krutai/ai-provider
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
---
|
|
22
|
-
|
|
23
19
|
## Quick Start
|
|
24
20
|
|
|
25
|
-
### Simplest usage (no setup needed)
|
|
26
|
-
|
|
27
|
-
The OpenRouter API key is built-in by default — just install and call:
|
|
28
|
-
|
|
29
21
|
```typescript
|
|
30
22
|
import { krutAI } from '@krutai/ai-provider';
|
|
31
23
|
|
|
32
|
-
const ai = krutAI(
|
|
33
|
-
|
|
24
|
+
const ai = krutAI({
|
|
25
|
+
apiKey: 'your-krutai-api-key',
|
|
26
|
+
serverUrl: 'https://ai.yourapp.com', // your deployed LangChain server
|
|
27
|
+
});
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
await ai.initialize(); // validates key with your server
|
|
30
|
+
|
|
31
|
+
// Single response
|
|
32
|
+
const text = await ai.generate('Write a poem about TypeScript');
|
|
36
33
|
console.log(text);
|
|
37
34
|
```
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
## Usage
|
|
40
37
|
|
|
41
|
-
###
|
|
38
|
+
### Generate (single response)
|
|
42
39
|
|
|
43
40
|
```typescript
|
|
44
|
-
const ai = krutAI({
|
|
41
|
+
const ai = krutAI({
|
|
42
|
+
apiKey: process.env.KRUTAI_API_KEY!,
|
|
43
|
+
serverUrl: 'https://ai.yourapp.com',
|
|
44
|
+
model: 'gpt-4o', // optional — server's default is used if omitted
|
|
45
|
+
});
|
|
46
|
+
|
|
45
47
|
await ai.initialize();
|
|
46
48
|
|
|
47
|
-
const text = await ai.generate('
|
|
49
|
+
const text = await ai.generate('Explain async/await in JavaScript', {
|
|
50
|
+
system: 'You are a helpful coding tutor.',
|
|
51
|
+
maxTokens: 500,
|
|
52
|
+
temperature: 0.7,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log(text);
|
|
48
56
|
```
|
|
49
57
|
|
|
50
58
|
### Streaming
|
|
51
59
|
|
|
52
60
|
```typescript
|
|
53
|
-
const ai = krutAI(
|
|
61
|
+
const ai = krutAI({
|
|
62
|
+
apiKey: process.env.KRUTAI_API_KEY!,
|
|
63
|
+
serverUrl: 'https://ai.yourapp.com',
|
|
64
|
+
});
|
|
65
|
+
|
|
54
66
|
await ai.initialize();
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
for await (const chunk of stream) {
|
|
58
|
-
process.stdout.write(chunk
|
|
68
|
+
// stream() is an async generator
|
|
69
|
+
for await (const chunk of ai.stream('Tell me a short story')) {
|
|
70
|
+
process.stdout.write(chunk);
|
|
59
71
|
}
|
|
60
72
|
```
|
|
61
73
|
|
|
62
|
-
### Multi-turn
|
|
74
|
+
### Multi-turn Chat
|
|
63
75
|
|
|
64
76
|
```typescript
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
]);
|
|
70
|
-
```
|
|
77
|
+
const ai = krutAI({
|
|
78
|
+
apiKey: process.env.KRUTAI_API_KEY!,
|
|
79
|
+
serverUrl: 'https://ai.yourapp.com',
|
|
80
|
+
});
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
await ai.initialize();
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
const response = await ai.chat([
|
|
85
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
86
|
+
{ role: 'user', content: 'What is the capital of France?' },
|
|
87
|
+
{ role: 'assistant', content: 'Paris.' },
|
|
88
|
+
{ role: 'user', content: 'What is it famous for?' },
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
console.log(response);
|
|
80
92
|
```
|
|
81
93
|
|
|
82
|
-
###
|
|
94
|
+
### Skip validation (useful for tests)
|
|
83
95
|
|
|
84
96
|
```typescript
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
openRouterApiKey: process.env.OPENROUTER_API_KEY!,
|
|
90
|
-
model: 'google/gemini-flash-1.5', // optional override
|
|
91
|
-
validateOnInit: true, // default
|
|
97
|
+
const ai = krutAI({
|
|
98
|
+
apiKey: 'test-key',
|
|
99
|
+
serverUrl: 'http://localhost:3000',
|
|
100
|
+
validateOnInit: false, // skips the /validate round-trip
|
|
92
101
|
});
|
|
93
102
|
|
|
94
|
-
|
|
95
|
-
const text = await ai.generate('
|
|
103
|
+
// No need to call initialize() when validateOnInit is false
|
|
104
|
+
const text = await ai.generate('Hello!');
|
|
96
105
|
```
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
## API Reference
|
|
101
|
-
|
|
102
|
-
### `krutAI(config?)` — factory function
|
|
103
|
-
|
|
104
|
-
| Field | Type | Default |
|
|
105
|
-
|---|---|---|
|
|
106
|
-
| `openRouterApiKey` | `string` | `process.env.OPENROUTER_API_KEY` |
|
|
107
|
-
| `model` | `string` | `"qwen/qwen3-235b-a22b-thinking-2507"` |
|
|
108
|
-
| `validateOnInit` | `boolean` | `true` |
|
|
109
|
-
| `validationEndpoint` | `string` | `undefined` (placeholder) |
|
|
110
|
-
|
|
111
|
-
### `KrutAIProvider` class
|
|
107
|
+
## Server API Contract
|
|
112
108
|
|
|
113
|
-
|
|
114
|
-
|---|---|---|
|
|
115
|
-
| `initialize()` | `Promise<void>` | Validates key + sets up OpenRouter client |
|
|
116
|
-
| `generate(prompt, opts?)` | `Promise<string>` | Single response |
|
|
117
|
-
| `stream(prompt, opts?)` | async iterable | Streaming response |
|
|
118
|
-
| `chat(messages, opts?)` | `Promise<string>` | Multi-turn conversation |
|
|
119
|
-
| `getModel()` | `string` | Active model name |
|
|
120
|
-
| `getClient()` | `OpenRouter` | Raw `@openrouter/sdk` client (advanced) |
|
|
121
|
-
| `isInitialized()` | `boolean` | Ready check |
|
|
109
|
+
Your LangChain server must expose these endpoints:
|
|
122
110
|
|
|
123
|
-
|
|
111
|
+
| Endpoint | Method | Auth | Body |
|
|
112
|
+
|---|---|---|---|
|
|
113
|
+
| `/validate` | POST | `x-api-key` header | `{ "apiKey": "..." }` |
|
|
114
|
+
| `/generate` | POST | `Authorization: Bearer <key>` | `{ "prompt": "...", "model": "...", ... }` |
|
|
115
|
+
| `/stream` | POST | `Authorization: Bearer <key>` | `{ "prompt": "...", "model": "...", ... }` |
|
|
116
|
+
| `/chat` | POST | `Authorization: Bearer <key>` | `{ "messages": [...], "model": "...", ... }` |
|
|
124
117
|
|
|
125
|
-
|
|
118
|
+
**Validation response:** `{ "valid": true }` or `{ "valid": false, "message": "reason" }`
|
|
126
119
|
|
|
127
|
-
|
|
128
|
-
qwen/qwen3-235b-a22b-thinking-2507
|
|
129
|
-
```
|
|
120
|
+
**AI response:** `{ "text": "..." }` or `{ "content": "..." }` or `{ "message": "..." }`
|
|
130
121
|
|
|
131
|
-
|
|
132
|
-
Browse all available models at https://openrouter.ai/models.
|
|
122
|
+
**Stream:** `text/event-stream` with `data: <chunk>` lines, ending with `data: [DONE]`
|
|
133
123
|
|
|
134
|
-
|
|
124
|
+
## API Reference
|
|
135
125
|
|
|
136
|
-
|
|
126
|
+
### `krutAI(config)`
|
|
137
127
|
|
|
138
|
-
|
|
128
|
+
Factory function — preferred way to create a provider.
|
|
139
129
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
130
|
+
```typescript
|
|
131
|
+
const ai = krutAI({
|
|
132
|
+
apiKey: string; // required
|
|
133
|
+
serverUrl: string; // required — base URL of your LangChain server
|
|
134
|
+
model?: string; // optional — passed to server (default: 'default')
|
|
135
|
+
validateOnInit?: boolean; // optional — default: true
|
|
136
|
+
});
|
|
143
137
|
```
|
|
144
|
-
Expected response: `{ "valid": true }` (or any `2xx` without `valid: false`).
|
|
145
|
-
|
|
146
|
-
> The live endpoint will be wired in once you deploy the POST route.
|
|
147
138
|
|
|
148
|
-
|
|
139
|
+
### `KrutAIProvider`
|
|
149
140
|
|
|
150
|
-
|
|
141
|
+
Full class API with the same methods as above. Use when you need the class directly.
|
|
151
142
|
|
|
152
|
-
|
|
153
|
-
- [`@krutai/auth`](https://www.npmjs.com/package/@krutai/auth) — Authentication (wraps better-auth)
|
|
154
|
-
- [`@krutai/rbac`](https://www.npmjs.com/package/@krutai/rbac) — Role-Based Access Control
|
|
143
|
+
### Exports
|
|
155
144
|
|
|
156
|
-
|
|
145
|
+
```typescript
|
|
146
|
+
export { krutAI, KrutAIProvider, KrutAIKeyValidationError, validateApiKey, validateApiKeyFormat, DEFAULT_MODEL };
|
|
147
|
+
export type { KrutAIProviderConfig, GenerateOptions, ChatMessage };
|
|
148
|
+
```
|
|
157
149
|
|
|
158
|
-
##
|
|
150
|
+
## License
|
|
159
151
|
|
|
160
|
-
|
|
161
|
-
- Available Models: https://openrouter.ai/models
|
|
162
|
-
- GitHub: https://github.com/AccountantAIOrg/krut_packages
|
|
163
|
-
- npm: https://www.npmjs.com/package/@krutai/ai-provider
|
|
152
|
+
MIT
|