@layer-ai/sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +288 -0
- package/dist/client.d.ts +19 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +59 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/loader.d.ts +7 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +21 -0
- package/dist/config/parser.d.ts +5 -0
- package/dist/config/parser.d.ts.map +1 -0
- package/dist/config/parser.js +12 -0
- package/dist/config/validator.d.ts +3 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +36 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/resources/gates.d.ts +51 -0
- package/dist/resources/gates.d.ts.map +1 -0
- package/dist/resources/gates.js +83 -0
- package/dist/resources/keys.d.ts +30 -0
- package/dist/resources/keys.d.ts.map +1 -0
- package/dist/resources/keys.js +46 -0
- package/dist/resources/logs.d.ts +8 -0
- package/dist/resources/logs.d.ts.map +1 -0
- package/dist/resources/logs.js +20 -0
- package/dist/types/api.d.ts +35 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +1 -0
- package/dist/types/config.d.ts +13 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +1 -0
- package/dist/types/gates.d.ts +26 -0
- package/dist/types/gates.d.ts.map +1 -0
- package/dist/types/gates.js +3 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/keys.d.ts +11 -0
- package/dist/types/keys.d.ts.map +1 -0
- package/dist/types/keys.js +1 -0
- package/dist/types/logs.d.ts +21 -0
- package/dist/types/logs.d.ts.map +1 -0
- package/dist/types/logs.js +1 -0
- package/dist/types/model-registry.d.ts +395 -0
- package/dist/types/model-registry.d.ts.map +1 -0
- package/dist/types/model-registry.js +338 -0
- package/dist/types/models.d.ts +76 -0
- package/dist/types/models.d.ts.map +1 -0
- package/dist/types/models.js +7 -0
- package/dist/types/smart-routing.d.ts +6 -0
- package/dist/types/smart-routing.d.ts.map +1 -0
- package/dist/types/smart-routing.js +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Layer AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# @layer-ai/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript SDK for Layer AI - Manage LLM requests with intelligent routing and fallbacks.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @layer-ai/sdk
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @layer-ai/sdk
|
|
11
|
+
# or
|
|
12
|
+
yarn add @layer-ai/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Layer } from '@layer-ai/sdk';
|
|
19
|
+
|
|
20
|
+
const layer = new Layer({
|
|
21
|
+
apiKey: process.env.LAYER_API_KEY,
|
|
22
|
+
baseUrl: 'http://localhost:3001'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Complete a request through a gate
|
|
26
|
+
const response = await layer.complete({
|
|
27
|
+
gate: 'my-gate',
|
|
28
|
+
prompt: 'Explain quantum computing in simple terms'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
console.log(response.text);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
### Constructor Options
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const layer = new Layer({
|
|
40
|
+
apiKey: string; // Required: Your Layer API key
|
|
41
|
+
baseUrl?: string; // Optional: API base URL (default: http://localhost:3001)
|
|
42
|
+
adminMode?: boolean; // Optional: Enable mutation operations (default: false)
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Admin Mode
|
|
47
|
+
|
|
48
|
+
By default, the SDK is read-only to prevent accidental mutations in production. To enable create/update/delete operations, set `adminMode: true`:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const layer = new Layer({
|
|
52
|
+
apiKey: process.env.LAYER_API_KEY,
|
|
53
|
+
adminMode: true // Required for mutations
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Now you can create/update/delete gates and keys
|
|
57
|
+
await layer.gates.create({
|
|
58
|
+
name: 'my-gate',
|
|
59
|
+
model: 'gpt-4o',
|
|
60
|
+
temperature: 0.7
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Note:** Admin mode is intended for setup scripts and infrastructure-as-code. For ongoing management, use the CLI or config files.
|
|
65
|
+
|
|
66
|
+
## API Reference
|
|
67
|
+
|
|
68
|
+
### Completions
|
|
69
|
+
|
|
70
|
+
#### `layer.complete(params)`
|
|
71
|
+
|
|
72
|
+
Send a completion request through a gate.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const response = await layer.complete({
|
|
76
|
+
gate: 'my-gate',
|
|
77
|
+
prompt: 'What is the capital of France?',
|
|
78
|
+
|
|
79
|
+
// Optional overrides (if gate allows)
|
|
80
|
+
model?: 'gpt-4o',
|
|
81
|
+
temperature?: 0.8,
|
|
82
|
+
maxTokens?: 500,
|
|
83
|
+
topP?: 0.9
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Response shape
|
|
87
|
+
{
|
|
88
|
+
text: string;
|
|
89
|
+
model: string;
|
|
90
|
+
usage: {
|
|
91
|
+
promptTokens: number;
|
|
92
|
+
completionTokens: number;
|
|
93
|
+
totalTokens: number;
|
|
94
|
+
};
|
|
95
|
+
cost: number;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Gates
|
|
100
|
+
|
|
101
|
+
#### `layer.gates.list()`
|
|
102
|
+
|
|
103
|
+
List all gates.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const gates = await layer.gates.list();
|
|
107
|
+
// Returns: Gate[]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### `layer.gates.get(name)`
|
|
111
|
+
|
|
112
|
+
Get a specific gate by name.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const gate = await layer.gates.get('my-gate');
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### `layer.gates.create(data)` ⚠️ Requires Admin Mode
|
|
119
|
+
|
|
120
|
+
Create a new gate.
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
await layer.gates.create({
|
|
124
|
+
name: 'my-gate',
|
|
125
|
+
model: 'gpt-4o',
|
|
126
|
+
description: 'My custom gate',
|
|
127
|
+
systemPrompt: 'You are a helpful assistant',
|
|
128
|
+
temperature: 0.7,
|
|
129
|
+
maxTokens: 1000,
|
|
130
|
+
topP: 1.0,
|
|
131
|
+
allowOverrides: true, // or specific fields: ['temperature', 'maxTokens']
|
|
132
|
+
routingStrategy: 'fallback',
|
|
133
|
+
fallbackModels: ['claude-sonnet-4', 'gemini-2.0-flash-exp'],
|
|
134
|
+
tags: ['production', 'general']
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### `layer.gates.update(name, data)` ⚠️ Requires Admin Mode
|
|
139
|
+
|
|
140
|
+
Update an existing gate.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
await layer.gates.update('my-gate', {
|
|
144
|
+
temperature: 0.8,
|
|
145
|
+
maxTokens: 1500
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `layer.gates.delete(name)` ⚠️ Requires Admin Mode
|
|
150
|
+
|
|
151
|
+
Delete a gate.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
await layer.gates.delete('my-gate');
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### API Keys
|
|
158
|
+
|
|
159
|
+
#### `layer.keys.list()`
|
|
160
|
+
|
|
161
|
+
List all API keys.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const keys = await layer.keys.list();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### `layer.keys.create(name)` ⚠️ Requires Admin Mode
|
|
168
|
+
|
|
169
|
+
Create a new API key.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const key = await layer.keys.create('my-app-key');
|
|
173
|
+
// Returns: { id: string, name: string, key: string, createdAt: string }
|
|
174
|
+
// Save the key - it's only shown once!
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `layer.keys.delete(id)` ⚠️ Requires Admin Mode
|
|
178
|
+
|
|
179
|
+
Revoke an API key.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
await layer.keys.delete('key-id');
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Logs
|
|
186
|
+
|
|
187
|
+
#### `layer.logs.list(options?)`
|
|
188
|
+
|
|
189
|
+
List request logs.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const logs = await layer.logs.list({
|
|
193
|
+
limit: 100,
|
|
194
|
+
offset: 0,
|
|
195
|
+
gateName: 'my-gate' // Optional filter
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## TypeScript Support
|
|
200
|
+
|
|
201
|
+
The SDK is written in TypeScript and provides full type definitions:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { Layer, Gate, CompletionRequest, CompletionResponse } from '@layer-ai/sdk';
|
|
205
|
+
|
|
206
|
+
const layer = new Layer({ apiKey: 'key' });
|
|
207
|
+
|
|
208
|
+
// All methods are fully typed
|
|
209
|
+
const response: CompletionResponse = await layer.complete({
|
|
210
|
+
gate: 'my-gate',
|
|
211
|
+
prompt: 'Hello'
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Error Handling
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
try {
|
|
219
|
+
const response = await layer.complete({
|
|
220
|
+
gate: 'my-gate',
|
|
221
|
+
prompt: 'Hello'
|
|
222
|
+
});
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (error instanceof Error) {
|
|
225
|
+
console.error('Layer error:', error.message);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Examples
|
|
231
|
+
|
|
232
|
+
### Basic Completion
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { Layer } from '@layer-ai/sdk';
|
|
236
|
+
|
|
237
|
+
const layer = new Layer({
|
|
238
|
+
apiKey: process.env.LAYER_API_KEY
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const response = await layer.complete({
|
|
242
|
+
gate: 'default',
|
|
243
|
+
prompt: 'Explain machine learning'
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
console.log(response.text);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### With Parameter Overrides
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
const response = await layer.complete({
|
|
253
|
+
gate: 'my-gate',
|
|
254
|
+
prompt: 'Write a haiku about coding',
|
|
255
|
+
temperature: 0.9, // More creative
|
|
256
|
+
maxTokens: 100
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Infrastructure as Code
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { Layer } from '@layer-ai/sdk';
|
|
264
|
+
|
|
265
|
+
const layer = new Layer({
|
|
266
|
+
apiKey: process.env.LAYER_API_KEY,
|
|
267
|
+
adminMode: true
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Create gates programmatically
|
|
271
|
+
await layer.gates.create({
|
|
272
|
+
name: 'production-gate',
|
|
273
|
+
model: 'gpt-4o',
|
|
274
|
+
temperature: 0.7,
|
|
275
|
+
routingStrategy: 'fallback',
|
|
276
|
+
fallbackModels: ['claude-sonnet-4']
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await layer.gates.create({
|
|
280
|
+
name: 'dev-gate',
|
|
281
|
+
model: 'gpt-4o-mini',
|
|
282
|
+
temperature: 0.5
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LayerConfig, RequestOptions } from './types.js';
|
|
2
|
+
import type { CompletionRequest, CompletionResponse } from './types/index.js';
|
|
3
|
+
import { GatesResource } from './resources/gates.js';
|
|
4
|
+
import { KeysResource } from './resources/keys.js';
|
|
5
|
+
import { LogsResource } from './resources/logs.js';
|
|
6
|
+
export declare class Layer {
|
|
7
|
+
private apiKey;
|
|
8
|
+
private baseUrl;
|
|
9
|
+
private adminMode;
|
|
10
|
+
gates: GatesResource;
|
|
11
|
+
keys: KeysResource;
|
|
12
|
+
logs: LogsResource;
|
|
13
|
+
constructor(config: LayerConfig);
|
|
14
|
+
/** @internal */
|
|
15
|
+
checkAdminMode(): void;
|
|
16
|
+
request<T>(options: RequestOptions): Promise<T>;
|
|
17
|
+
complete(params: CompletionRequest): Promise<CompletionResponse>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAiB,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAU;IAEpB,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,YAAY,CAAC;gBAEd,MAAM,EAAE,WAAW;IAa/B,gBAAgB;IAChB,cAAc,IAAI,IAAI;IAgBT,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IA4BtD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAOvE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { GatesResource } from './resources/gates.js';
|
|
2
|
+
import { KeysResource } from './resources/keys.js';
|
|
3
|
+
import { LogsResource } from './resources/logs.js';
|
|
4
|
+
export class Layer {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
if (!config.apiKey) {
|
|
7
|
+
throw new Error('Layer API key is required');
|
|
8
|
+
}
|
|
9
|
+
this.apiKey = config.apiKey;
|
|
10
|
+
this.baseUrl = config.baseUrl || 'http://localhost:3001';
|
|
11
|
+
this.adminMode = config.adminMode || false;
|
|
12
|
+
this.gates = new GatesResource(this);
|
|
13
|
+
this.keys = new KeysResource(this);
|
|
14
|
+
this.logs = new LogsResource(this);
|
|
15
|
+
}
|
|
16
|
+
/** @internal */
|
|
17
|
+
checkAdminMode() {
|
|
18
|
+
if (!this.adminMode) {
|
|
19
|
+
throw new Error('This operation requires adminMode: true in Layer constructor.\n\n' +
|
|
20
|
+
'Example:\n' +
|
|
21
|
+
' const layer = new Layer({ apiKey: "...", adminMode: true });\n\n' +
|
|
22
|
+
'Admin mode is required for mutation operations:\n' +
|
|
23
|
+
' - gates.create/update/delete()\n' +
|
|
24
|
+
' - keys.create/delete()\n\n' +
|
|
25
|
+
'These methods are intended for setup scripts only.\n' +
|
|
26
|
+
'For ongoing managmenent, use CLI or config files.\n\n' +
|
|
27
|
+
'See: https://docs.uselayer.ai/sdk/admin-mode');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async request(options) {
|
|
31
|
+
const { method, path, body } = options;
|
|
32
|
+
const url = `${this.baseUrl}${path}`;
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
method,
|
|
35
|
+
headers: {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
38
|
+
},
|
|
39
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
40
|
+
});
|
|
41
|
+
// Handle 204 No Content responses (e.g., DELETE operations)
|
|
42
|
+
if (response.status === 204) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const error = data;
|
|
48
|
+
throw new Error(error.message || error.error);
|
|
49
|
+
}
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
async complete(params) {
|
|
53
|
+
return this.request({
|
|
54
|
+
method: 'POST',
|
|
55
|
+
path: '/v1/complete',
|
|
56
|
+
body: params,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LayerConfigFile } from '../types/index.js';
|
|
2
|
+
export declare function loadConfig(filePath: string): Promise<LayerConfigFile>;
|
|
3
|
+
/**
|
|
4
|
+
* Utility: Parse config from string (useful for testing)
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseConfig(yamlContent: string): LayerConfigFile;
|
|
7
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAe3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAGhE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import { parseYAML } from './parser.js';
|
|
3
|
+
import { validateConfig } from './validator.js';
|
|
4
|
+
export async function loadConfig(filePath) {
|
|
5
|
+
let content;
|
|
6
|
+
try {
|
|
7
|
+
content = await fs.readFile(filePath, 'utf-8');
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
throw new Error(`Failed to read config file at ${filePath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
11
|
+
}
|
|
12
|
+
const parsed = parseYAML(content);
|
|
13
|
+
return validateConfig(parsed);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Utility: Parse config from string (useful for testing)
|
|
17
|
+
*/
|
|
18
|
+
export function parseConfig(yamlContent) {
|
|
19
|
+
const parsed = parseYAML(yamlContent);
|
|
20
|
+
return validateConfig(parsed);
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/config/parser.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQlD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import YAML from 'yaml';
|
|
2
|
+
/**
|
|
3
|
+
* Parse YAML string into jscript object
|
|
4
|
+
*/
|
|
5
|
+
export function parseYAML(content) {
|
|
6
|
+
try {
|
|
7
|
+
return YAML.parse(content);
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
throw new Error(`Failed to parse YAML: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/config/validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAsCzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,CAE7D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const GateConfigSchema = z.object({
|
|
3
|
+
// Required fields
|
|
4
|
+
name: z.string().min(1, 'Gate name cannot be empty'),
|
|
5
|
+
model: z.string().min(1, 'Model cannot be empty'),
|
|
6
|
+
// Optional public fields
|
|
7
|
+
description: z.string().optional(),
|
|
8
|
+
systemPrompt: z.string().optional(),
|
|
9
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
10
|
+
maxTokens: z.number().positive().optional(),
|
|
11
|
+
topP: z.number().min(0).max(1).optional(),
|
|
12
|
+
routingStrategy: z.enum(['single', 'fallback', 'round-robin']).optional(),
|
|
13
|
+
fallbackModels: z.array(z.string()).optional(),
|
|
14
|
+
allowOverrides: z.union([
|
|
15
|
+
z.boolean(),
|
|
16
|
+
z.record(z.boolean())
|
|
17
|
+
]).optional(),
|
|
18
|
+
tags: z.array(z.string()).optional(),
|
|
19
|
+
// Internal fields (layer-ai-internal)
|
|
20
|
+
costWeight: z.number().min(0).max(1).optional(),
|
|
21
|
+
latencyWeight: z.number().min(0).max(1).optional(),
|
|
22
|
+
qualityWeight: z.number().min(0).max(1).optional(),
|
|
23
|
+
maxCostPer1kTokens: z.number().positive().optional(),
|
|
24
|
+
maxLatencyMs: z.number().positive().optional(),
|
|
25
|
+
taskAnalysis: z.object({
|
|
26
|
+
primary: z.string(),
|
|
27
|
+
alternatives: z.array(z.string()),
|
|
28
|
+
reasoning: z.string(),
|
|
29
|
+
}).optional(),
|
|
30
|
+
});
|
|
31
|
+
const LayerConfigFileSchema = z.object({
|
|
32
|
+
gates: z.array(GateConfigSchema).min(1, 'Config must contain at least one gate'),
|
|
33
|
+
});
|
|
34
|
+
export function validateConfig(data) {
|
|
35
|
+
return LayerConfigFileSchema.parse(data);
|
|
36
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Layer } from './client.js';
|
|
2
|
+
export type { LayerConfig } from './types.js';
|
|
3
|
+
export { KeysResource } from './resources/keys.js';
|
|
4
|
+
export { GatesResource } from './resources/gates.js';
|
|
5
|
+
export { LogsResource } from './resources/logs.js';
|
|
6
|
+
export * from './types/index.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Layer } from './client.js';
|
|
2
|
+
export { KeysResource } from './resources/keys.js';
|
|
3
|
+
export { GatesResource } from './resources/gates.js';
|
|
4
|
+
export { LogsResource } from './resources/logs.js';
|
|
5
|
+
// Re-export all types from types package
|
|
6
|
+
export * from './types/index.js';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Layer } from '../client.js';
|
|
2
|
+
import type { Gate, CreateGateRequest, UpdateGateRequest } from '../types/index.js';
|
|
3
|
+
import type { TaskAnalysis } from '../types/index.js';
|
|
4
|
+
export declare class GatesResource {
|
|
5
|
+
private client;
|
|
6
|
+
constructor(client: Layer);
|
|
7
|
+
/**
|
|
8
|
+
* Create a new gate.
|
|
9
|
+
*
|
|
10
|
+
* Requires `adminMode: true` in Layer constructor.
|
|
11
|
+
*
|
|
12
|
+
* @throws Error if adminMode is not enabled
|
|
13
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
14
|
+
*/
|
|
15
|
+
create(data: CreateGateRequest): Promise<Gate>;
|
|
16
|
+
/**
|
|
17
|
+
* Lists all gates
|
|
18
|
+
* No admin mode required.
|
|
19
|
+
*/
|
|
20
|
+
list(): Promise<Gate[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Gets a specific gate by name
|
|
23
|
+
* No admin mode required.
|
|
24
|
+
*/
|
|
25
|
+
get(name: string): Promise<Gate>;
|
|
26
|
+
/**
|
|
27
|
+
* Update an existing gate.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ Requires `adminMode: true` in Layer constructor.
|
|
30
|
+
*
|
|
31
|
+
* @throws Error if adminMode is not enabled
|
|
32
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
33
|
+
*/
|
|
34
|
+
update(name: string, data: UpdateGateRequest): Promise<Gate>;
|
|
35
|
+
/**
|
|
36
|
+
* Deletes an existing.
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ Requires `adminMode: true` in Layer constructor.
|
|
39
|
+
*
|
|
40
|
+
* @throws Error if adminMode is not enabled
|
|
41
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
42
|
+
*/
|
|
43
|
+
delete(name: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Get AI-powered model suggestions for a gate.
|
|
46
|
+
*
|
|
47
|
+
* Layer-AI Internal Feature - returns a 404 on self-hosted public API
|
|
48
|
+
*/
|
|
49
|
+
suggestions(gateName: string): Promise<TaskAnalysis>;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=gates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../src/resources/gates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,KAAK;IAEjC;;;;;;;OAOG;IACG,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IASpD;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAO7B;;;OAGG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtC;;;;;;;OAOG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE;;;;;;;OAOG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC;;;;OAIG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAM3D"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export class GatesResource {
|
|
2
|
+
constructor(client) {
|
|
3
|
+
this.client = client;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Create a new gate.
|
|
7
|
+
*
|
|
8
|
+
* Requires `adminMode: true` in Layer constructor.
|
|
9
|
+
*
|
|
10
|
+
* @throws Error if adminMode is not enabled
|
|
11
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
12
|
+
*/
|
|
13
|
+
async create(data) {
|
|
14
|
+
this.client.checkAdminMode();
|
|
15
|
+
return this.client.request({
|
|
16
|
+
method: 'POST',
|
|
17
|
+
path: '/v1/gates',
|
|
18
|
+
body: data,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Lists all gates
|
|
23
|
+
* No admin mode required.
|
|
24
|
+
*/
|
|
25
|
+
async list() {
|
|
26
|
+
return this.client.request({
|
|
27
|
+
method: 'GET',
|
|
28
|
+
path: '/v1/gates',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Gets a specific gate by name
|
|
33
|
+
* No admin mode required.
|
|
34
|
+
*/
|
|
35
|
+
async get(name) {
|
|
36
|
+
return this.client.request({
|
|
37
|
+
method: 'GET',
|
|
38
|
+
path: `/v1/gates/name/${name}`,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Update an existing gate.
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ Requires `adminMode: true` in Layer constructor.
|
|
45
|
+
*
|
|
46
|
+
* @throws Error if adminMode is not enabled
|
|
47
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
48
|
+
*/
|
|
49
|
+
async update(name, data) {
|
|
50
|
+
this.client.checkAdminMode();
|
|
51
|
+
return this.client.request({
|
|
52
|
+
method: 'PATCH',
|
|
53
|
+
path: `/v1/gates/name/${name}`,
|
|
54
|
+
body: data,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Deletes an existing.
|
|
59
|
+
*
|
|
60
|
+
* ⚠️ Requires `adminMode: true` in Layer constructor.
|
|
61
|
+
*
|
|
62
|
+
* @throws Error if adminMode is not enabled
|
|
63
|
+
* @see https://docs.uselayer.ai/sdk/admin-mode
|
|
64
|
+
*/
|
|
65
|
+
async delete(name) {
|
|
66
|
+
this.client.checkAdminMode();
|
|
67
|
+
await this.client.request({
|
|
68
|
+
method: 'DELETE',
|
|
69
|
+
path: `/v1/gates/name/${name}`,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get AI-powered model suggestions for a gate.
|
|
74
|
+
*
|
|
75
|
+
* Layer-AI Internal Feature - returns a 404 on self-hosted public API
|
|
76
|
+
*/
|
|
77
|
+
async suggestions(gateName) {
|
|
78
|
+
return this.client.request({
|
|
79
|
+
method: 'GET',
|
|
80
|
+
path: `/v1/gates/${gateName}/suggestions`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|