@patternzones/koine-sdk 1.1.6 → 2.0.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/README.md +33 -23
- package/dist/client.d.ts +57 -34
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +38 -278
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +18 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -1
- package/dist/http.d.ts +29 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +103 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/object.d.ts +55 -0
- package/dist/object.d.ts.map +1 -0
- package/dist/object.js +65 -0
- package/dist/object.js.map +1 -0
- package/dist/stream/index.d.ts +37 -0
- package/dist/stream/index.d.ts.map +1 -0
- package/dist/stream/index.js +170 -0
- package/dist/stream/index.js.map +1 -0
- package/dist/stream/sse.d.ts +9 -0
- package/dist/stream/sse.d.ts.map +1 -0
- package/dist/stream/sse.js +59 -0
- package/dist/stream/sse.js.map +1 -0
- package/dist/text.d.ts +36 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +48 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +26 -26
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -22,14 +22,15 @@ npm install @patternzones/koine-sdk
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
|
-
import {
|
|
25
|
+
import { createKoine } from '@patternzones/koine-sdk';
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const koine = createKoine({
|
|
28
28
|
baseUrl: 'http://localhost:3100',
|
|
29
29
|
authKey: 'your-api-key',
|
|
30
|
-
|
|
30
|
+
timeout: 300000, // 5 minutes
|
|
31
|
+
});
|
|
31
32
|
|
|
32
|
-
const result = await generateText(
|
|
33
|
+
const result = await koine.generateText({
|
|
33
34
|
prompt: 'Hello, how are you?',
|
|
34
35
|
});
|
|
35
36
|
|
|
@@ -39,32 +40,40 @@ console.log(result.text);
|
|
|
39
40
|
## Features
|
|
40
41
|
|
|
41
42
|
- **Text Generation** — `generateText()` for simple prompts
|
|
42
|
-
- **Streaming** — `streamText()` with async
|
|
43
|
+
- **Streaming** — `streamText()` with ReadableStream (async iterable)
|
|
43
44
|
- **Structured Output** — `generateObject()` with Zod schema validation
|
|
45
|
+
- **Cancellation** — AbortSignal support for all requests
|
|
44
46
|
- **Type Safety** — Full TypeScript types for all requests and responses
|
|
45
|
-
- **Error Handling** — `KoineError` class with
|
|
47
|
+
- **Error Handling** — `KoineError` class with typed error codes
|
|
46
48
|
|
|
47
49
|
## API
|
|
48
50
|
|
|
49
|
-
###
|
|
51
|
+
### Client Factory
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const koine = createKoine(config);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Creates a client instance with the given configuration. The config is validated once at creation time.
|
|
58
|
+
|
|
59
|
+
### Methods
|
|
50
60
|
|
|
51
|
-
|
|
|
52
|
-
|
|
53
|
-
| `generateText(
|
|
54
|
-
| `streamText(
|
|
55
|
-
| `generateObject(
|
|
61
|
+
| Method | Description |
|
|
62
|
+
|--------|-------------|
|
|
63
|
+
| `koine.generateText(options)` | Generate text from a prompt |
|
|
64
|
+
| `koine.streamText(options)` | Stream text via Server-Sent Events |
|
|
65
|
+
| `koine.generateObject(options)` | Extract structured data using a Zod schema |
|
|
56
66
|
|
|
57
67
|
### Types
|
|
58
68
|
|
|
59
69
|
| Type | Description |
|
|
60
70
|
|------|-------------|
|
|
61
71
|
| `KoineConfig` | Client configuration (baseUrl, authKey, timeout, model) |
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `KoineError` | Error class with status and code |
|
|
72
|
+
| `KoineClient` | Client interface returned by `createKoine()` |
|
|
73
|
+
| `KoineUsage` | Token usage stats (inputTokens, outputTokens, totalTokens) |
|
|
74
|
+
| `KoineStreamResult` | Streaming result with ReadableStream and promises |
|
|
75
|
+
| `KoineError` | Error class with typed `code` property |
|
|
76
|
+
| `KoineErrorCode` | Union type of all possible error codes |
|
|
68
77
|
|
|
69
78
|
## Documentation
|
|
70
79
|
|
|
@@ -78,13 +87,14 @@ See the [SDK Guide](https://github.com/pattern-zones-co/koine/blob/main/docs/sdk
|
|
|
78
87
|
|
|
79
88
|
## Examples
|
|
80
89
|
|
|
81
|
-
Runnable examples are available in [
|
|
90
|
+
Runnable examples are available in the [`examples/`](https://github.com/pattern-zones-co/koine/tree/main/packages/sdks/typescript/examples) directory. Run from the SDK directory using the npm scripts (which load `.env` from the project root):
|
|
82
91
|
|
|
83
92
|
```bash
|
|
84
|
-
|
|
85
|
-
bun run
|
|
86
|
-
bun run
|
|
87
|
-
bun run
|
|
93
|
+
cd packages/sdks/typescript
|
|
94
|
+
bun run example:hello # Basic text generation
|
|
95
|
+
bun run example:recipe # Structured output with Zod
|
|
96
|
+
bun run example:stream # Real-time streaming
|
|
97
|
+
bun run example:conversation # Multi-turn sessions
|
|
88
98
|
```
|
|
89
99
|
|
|
90
100
|
## License
|
package/dist/client.d.ts
CHANGED
|
@@ -1,39 +1,62 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import
|
|
1
|
+
import { type GenerateObjectOptions, type GenerateObjectResult, generateObject } from "./object.js";
|
|
2
|
+
import { type StreamTextOptions, streamText } from "./stream/index.js";
|
|
3
|
+
import { type GenerateTextOptions, type GenerateTextResult, generateText } from "./text.js";
|
|
4
|
+
import type { KoineConfig, KoineStreamResult } from "./types.js";
|
|
5
|
+
export { generateText, streamText, generateObject };
|
|
6
|
+
export type { GenerateTextOptions, GenerateTextResult, StreamTextOptions, GenerateObjectOptions, GenerateObjectResult, };
|
|
3
7
|
/**
|
|
4
|
-
*
|
|
8
|
+
* Koine client interface returned by createKoine.
|
|
5
9
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
export interface KoineClient {
|
|
11
|
+
/**
|
|
12
|
+
* Generates plain text response from Koine gateway service.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Request options
|
|
15
|
+
* @returns Object containing response text, usage stats, and session ID
|
|
16
|
+
* @throws {KoineError} When the request fails or returns invalid response
|
|
17
|
+
*/
|
|
18
|
+
generateText(options: GenerateTextOptions): Promise<GenerateTextResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Streams text response from Koine gateway service.
|
|
21
|
+
*
|
|
22
|
+
* @param options - Request options
|
|
23
|
+
* @returns KoineStreamResult with textStream and promises for sessionId, usage, text
|
|
24
|
+
* @throws {KoineError} When connection fails or stream encounters an error
|
|
25
|
+
*/
|
|
26
|
+
streamText(options: StreamTextOptions): Promise<KoineStreamResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Generates structured JSON response from Koine gateway service.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam T - The type of the expected response object, inferred from schema
|
|
31
|
+
* @param options - Request options including Zod schema
|
|
32
|
+
* @returns Object containing validated response, raw text, usage, and sessionId
|
|
33
|
+
* @throws {KoineError} With code 'VALIDATION_ERROR' if response doesn't match schema
|
|
34
|
+
*/
|
|
35
|
+
generateObject<T>(options: GenerateObjectOptions<T>): Promise<GenerateObjectResult<T>>;
|
|
36
|
+
}
|
|
15
37
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
38
|
+
* Creates a Koine client instance with the given configuration.
|
|
39
|
+
*
|
|
40
|
+
* @param config - Client configuration including baseUrl, authKey, and timeout
|
|
41
|
+
* @returns KoineClient with generateText, streamText, and generateObject methods
|
|
42
|
+
* @throws {KoineError} With code 'INVALID_CONFIG' if config is invalid
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import { createKoine } from '@patternzones/koine-sdk';
|
|
47
|
+
*
|
|
48
|
+
* const koine = createKoine({
|
|
49
|
+
* baseUrl: 'http://localhost:3100',
|
|
50
|
+
* authKey: 'your-api-key',
|
|
51
|
+
* timeout: 300000,
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* const result = await koine.generateText({
|
|
55
|
+
* prompt: 'Hello, how are you?',
|
|
56
|
+
* });
|
|
57
|
+
*
|
|
58
|
+
* console.log(result.text);
|
|
59
|
+
* ```
|
|
18
60
|
*/
|
|
19
|
-
export declare function
|
|
20
|
-
system?: string;
|
|
21
|
-
prompt: string;
|
|
22
|
-
sessionId?: string;
|
|
23
|
-
}): Promise<KoineStreamResult>;
|
|
24
|
-
/**
|
|
25
|
-
* Generates structured JSON response from Koine gateway service.
|
|
26
|
-
* Converts Zod schema to JSON Schema for the gateway service.
|
|
27
|
-
*/
|
|
28
|
-
export declare function generateObject<T>(config: KoineConfig, options: {
|
|
29
|
-
system?: string;
|
|
30
|
-
prompt: string;
|
|
31
|
-
schema: z.ZodSchema<T>;
|
|
32
|
-
sessionId?: string;
|
|
33
|
-
}): Promise<{
|
|
34
|
-
object: T;
|
|
35
|
-
rawText: string;
|
|
36
|
-
usage: KoineUsage;
|
|
37
|
-
sessionId: string;
|
|
38
|
-
}>;
|
|
61
|
+
export declare function createKoine(config: KoineConfig): KoineClient;
|
|
39
62
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,cAAc,EACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,YAAY,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AACpD,YAAY,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACpB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;;;OAMG;IACH,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAExE;;;;;;OAMG;IACH,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEnE;;;;;;;OAOG;IACH,cAAc,CAAC,CAAC,EACf,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAU5D"}
|
package/dist/client.js
CHANGED
|
@@ -1,286 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateText =
|
|
4
|
-
exports.
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
exports.generateObject = exports.streamText = exports.generateText = void 0;
|
|
4
|
+
exports.createKoine = createKoine;
|
|
5
|
+
// Import and re-export functions from the new modules
|
|
6
|
+
const http_js_1 = require("./http.js");
|
|
7
|
+
const object_js_1 = require("./object.js");
|
|
8
|
+
Object.defineProperty(exports, "generateObject", { enumerable: true, get: function () { return object_js_1.generateObject; } });
|
|
9
|
+
const index_js_1 = require("./stream/index.js");
|
|
10
|
+
Object.defineProperty(exports, "streamText", { enumerable: true, get: function () { return index_js_1.streamText; } });
|
|
11
|
+
const text_js_1 = require("./text.js");
|
|
12
|
+
Object.defineProperty(exports, "generateText", { enumerable: true, get: function () { return text_js_1.generateText; } });
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
14
|
+
* Creates a Koine client instance with the given configuration.
|
|
15
|
+
*
|
|
16
|
+
* @param config - Client configuration including baseUrl, authKey, and timeout
|
|
17
|
+
* @returns KoineClient with generateText, streamText, and generateObject methods
|
|
18
|
+
* @throws {KoineError} With code 'INVALID_CONFIG' if config is invalid
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createKoine } from '@patternzones/koine-sdk';
|
|
23
|
+
*
|
|
24
|
+
* const koine = createKoine({
|
|
25
|
+
* baseUrl: 'http://localhost:3100',
|
|
26
|
+
* authKey: 'your-api-key',
|
|
27
|
+
* timeout: 300000,
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* const result = await koine.generateText({
|
|
31
|
+
* prompt: 'Hello, how are you?',
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* console.log(result.text);
|
|
35
|
+
* ```
|
|
10
36
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return JSON.parse(text);
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Generates plain text response from Koine gateway service.
|
|
22
|
-
*/
|
|
23
|
-
async function generateText(config, options) {
|
|
24
|
-
const response = await fetch(`${config.baseUrl}/generate-text`, {
|
|
25
|
-
method: "POST",
|
|
26
|
-
headers: {
|
|
27
|
-
"Content-Type": "application/json",
|
|
28
|
-
Authorization: `Bearer ${config.authKey}`,
|
|
29
|
-
},
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
system: options.system,
|
|
32
|
-
prompt: options.prompt,
|
|
33
|
-
sessionId: options.sessionId,
|
|
34
|
-
model: config.model,
|
|
35
|
-
}),
|
|
36
|
-
signal: AbortSignal.timeout(config.timeout),
|
|
37
|
-
});
|
|
38
|
-
if (!response.ok) {
|
|
39
|
-
const errorBody = await safeJsonParse(response);
|
|
40
|
-
throw new errors_js_1.KoineError(errorBody?.error || `HTTP ${response.status} ${response.statusText}`, errorBody?.code || "HTTP_ERROR", errorBody?.rawText);
|
|
41
|
-
}
|
|
42
|
-
const result = await safeJsonParse(response);
|
|
43
|
-
if (!result) {
|
|
44
|
-
throw new errors_js_1.KoineError("Invalid response from Koine gateway: expected JSON", "INVALID_RESPONSE");
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
text: result.text,
|
|
48
|
-
usage: result.usage,
|
|
49
|
-
sessionId: result.sessionId,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Parses SSE events from a ReadableStream.
|
|
54
|
-
* SSE format: "event: name\ndata: {...}\n\n"
|
|
55
|
-
*/
|
|
56
|
-
function createSSEParser() {
|
|
57
|
-
let buffer = "";
|
|
58
|
-
// Reuse decoder with stream mode to correctly handle multi-byte UTF-8 chars spanning chunks
|
|
59
|
-
const decoder = new TextDecoder();
|
|
60
|
-
return new TransformStream({
|
|
61
|
-
transform(chunk, controller) {
|
|
62
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
63
|
-
// SSE events are separated by double newlines
|
|
64
|
-
const events = buffer.split("\n\n");
|
|
65
|
-
// Keep the last potentially incomplete event in the buffer
|
|
66
|
-
buffer = events.pop() || "";
|
|
67
|
-
for (const eventStr of events) {
|
|
68
|
-
if (!eventStr.trim())
|
|
69
|
-
continue;
|
|
70
|
-
const lines = eventStr.split("\n");
|
|
71
|
-
let eventType = "";
|
|
72
|
-
let data = "";
|
|
73
|
-
for (const line of lines) {
|
|
74
|
-
if (line.startsWith("event: ")) {
|
|
75
|
-
eventType = line.slice(7);
|
|
76
|
-
}
|
|
77
|
-
else if (line.startsWith("data: ")) {
|
|
78
|
-
data = line.slice(6);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (eventType && data) {
|
|
82
|
-
controller.enqueue({ event: eventType, data });
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
flush(controller) {
|
|
87
|
-
// Process any remaining data in buffer
|
|
88
|
-
if (buffer.trim()) {
|
|
89
|
-
const lines = buffer.split("\n");
|
|
90
|
-
let eventType = "";
|
|
91
|
-
let data = "";
|
|
92
|
-
for (const line of lines) {
|
|
93
|
-
if (line.startsWith("event: ")) {
|
|
94
|
-
eventType = line.slice(7);
|
|
95
|
-
}
|
|
96
|
-
else if (line.startsWith("data: ")) {
|
|
97
|
-
data = line.slice(6);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (eventType && data) {
|
|
101
|
-
controller.enqueue({ event: eventType, data });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Streams text response from Koine gateway service.
|
|
109
|
-
* Returns a ReadableStream of text chunks that can be consumed as they arrive.
|
|
110
|
-
*/
|
|
111
|
-
async function streamText(config, options) {
|
|
112
|
-
const response = await fetch(`${config.baseUrl}/stream`, {
|
|
113
|
-
method: "POST",
|
|
114
|
-
headers: {
|
|
115
|
-
"Content-Type": "application/json",
|
|
116
|
-
Authorization: `Bearer ${config.authKey}`,
|
|
117
|
-
},
|
|
118
|
-
body: JSON.stringify({
|
|
119
|
-
system: options.system,
|
|
120
|
-
prompt: options.prompt,
|
|
121
|
-
sessionId: options.sessionId,
|
|
122
|
-
model: config.model,
|
|
123
|
-
}),
|
|
124
|
-
signal: AbortSignal.timeout(config.timeout),
|
|
125
|
-
});
|
|
126
|
-
if (!response.ok) {
|
|
127
|
-
const errorBody = await safeJsonParse(response);
|
|
128
|
-
throw new errors_js_1.KoineError(errorBody?.error || `HTTP ${response.status} ${response.statusText}`, errorBody?.code || "HTTP_ERROR", errorBody?.rawText);
|
|
129
|
-
}
|
|
130
|
-
if (!response.body) {
|
|
131
|
-
throw new errors_js_1.KoineError("No response body from Koine gateway", "NO_RESPONSE_BODY");
|
|
132
|
-
}
|
|
133
|
-
// Set up promises for session, usage, and accumulated text
|
|
134
|
-
let resolveSessionId;
|
|
135
|
-
let rejectSessionId;
|
|
136
|
-
const sessionIdPromise = new Promise((resolve, reject) => {
|
|
137
|
-
resolveSessionId = resolve;
|
|
138
|
-
rejectSessionId = reject;
|
|
139
|
-
});
|
|
140
|
-
let resolveUsage;
|
|
141
|
-
let rejectUsage;
|
|
142
|
-
const usagePromise = new Promise((resolve, reject) => {
|
|
143
|
-
resolveUsage = resolve;
|
|
144
|
-
rejectUsage = reject;
|
|
145
|
-
});
|
|
146
|
-
let resolveText;
|
|
147
|
-
let rejectText;
|
|
148
|
-
const textPromise = new Promise((resolve, reject) => {
|
|
149
|
-
resolveText = resolve;
|
|
150
|
-
rejectText = reject;
|
|
151
|
-
});
|
|
152
|
-
let accumulatedText = "";
|
|
153
|
-
let sessionIdReceived = false;
|
|
154
|
-
let usageReceived = false;
|
|
155
|
-
// Transform SSE events into text chunks
|
|
156
|
-
const textStream = response.body.pipeThrough(createSSEParser()).pipeThrough(new TransformStream({
|
|
157
|
-
transform(sseEvent, controller) {
|
|
158
|
-
// Critical events (session, result, error, done) must propagate parse errors
|
|
159
|
-
// Text events can log and continue - degraded content is better than total failure
|
|
160
|
-
const isCriticalEvent = ["session", "result", "error", "done"].includes(sseEvent.event);
|
|
161
|
-
try {
|
|
162
|
-
switch (sseEvent.event) {
|
|
163
|
-
case "session": {
|
|
164
|
-
const parsed = JSON.parse(sseEvent.data);
|
|
165
|
-
if (!sessionIdReceived) {
|
|
166
|
-
sessionIdReceived = true;
|
|
167
|
-
resolveSessionId(parsed.sessionId);
|
|
168
|
-
}
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
case "text": {
|
|
172
|
-
const parsed = JSON.parse(sseEvent.data);
|
|
173
|
-
accumulatedText += parsed.text;
|
|
174
|
-
controller.enqueue(parsed.text);
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
case "result": {
|
|
178
|
-
const parsed = JSON.parse(sseEvent.data);
|
|
179
|
-
usageReceived = true;
|
|
180
|
-
resolveUsage(parsed.usage);
|
|
181
|
-
if (!sessionIdReceived) {
|
|
182
|
-
sessionIdReceived = true;
|
|
183
|
-
resolveSessionId(parsed.sessionId);
|
|
184
|
-
}
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
case "error": {
|
|
188
|
-
const parsed = JSON.parse(sseEvent.data);
|
|
189
|
-
const error = new errors_js_1.KoineError(parsed.error, parsed.code || "STREAM_ERROR");
|
|
190
|
-
usageReceived = true; // Prevent double rejection in flush
|
|
191
|
-
rejectUsage(error);
|
|
192
|
-
rejectText(error);
|
|
193
|
-
if (!sessionIdReceived) {
|
|
194
|
-
rejectSessionId(error);
|
|
195
|
-
}
|
|
196
|
-
controller.error(error);
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
case "done": {
|
|
200
|
-
// Stream complete, resolve the text promise
|
|
201
|
-
resolveText(accumulatedText);
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
catch (parseError) {
|
|
207
|
-
if (isCriticalEvent) {
|
|
208
|
-
// Critical event parse failure - propagate error
|
|
209
|
-
const error = new errors_js_1.KoineError(`Failed to parse critical SSE event: ${sseEvent.event}`, "SSE_PARSE_ERROR");
|
|
210
|
-
if (!usageReceived) {
|
|
211
|
-
usageReceived = true;
|
|
212
|
-
rejectUsage(error);
|
|
213
|
-
}
|
|
214
|
-
rejectText(error);
|
|
215
|
-
if (!sessionIdReceived) {
|
|
216
|
-
rejectSessionId(error);
|
|
217
|
-
}
|
|
218
|
-
controller.error(error);
|
|
219
|
-
}
|
|
220
|
-
// Non-critical event (text) - continue stream silently
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
flush() {
|
|
224
|
-
// Handle promises that were never resolved/rejected during stream
|
|
225
|
-
if (!sessionIdReceived) {
|
|
226
|
-
rejectSessionId(new errors_js_1.KoineError("Stream ended without session ID", "NO_SESSION"));
|
|
227
|
-
}
|
|
228
|
-
if (!usageReceived) {
|
|
229
|
-
rejectUsage(new errors_js_1.KoineError("Stream ended without usage information", "NO_USAGE"));
|
|
230
|
-
}
|
|
231
|
-
resolveText(accumulatedText);
|
|
232
|
-
},
|
|
233
|
-
}));
|
|
234
|
-
return {
|
|
235
|
-
textStream,
|
|
236
|
-
sessionId: sessionIdPromise,
|
|
237
|
-
usage: usagePromise,
|
|
238
|
-
text: textPromise,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Generates structured JSON response from Koine gateway service.
|
|
243
|
-
* Converts Zod schema to JSON Schema for the gateway service.
|
|
244
|
-
*/
|
|
245
|
-
async function generateObject(config, options) {
|
|
246
|
-
// Convert Zod schema to JSON Schema for the gateway service
|
|
247
|
-
const jsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(options.schema, {
|
|
248
|
-
$refStrategy: "none",
|
|
249
|
-
target: "jsonSchema7",
|
|
250
|
-
});
|
|
251
|
-
const response = await fetch(`${config.baseUrl}/generate-object`, {
|
|
252
|
-
method: "POST",
|
|
253
|
-
headers: {
|
|
254
|
-
"Content-Type": "application/json",
|
|
255
|
-
Authorization: `Bearer ${config.authKey}`,
|
|
256
|
-
},
|
|
257
|
-
body: JSON.stringify({
|
|
258
|
-
system: options.system,
|
|
259
|
-
prompt: options.prompt,
|
|
260
|
-
schema: jsonSchema,
|
|
261
|
-
sessionId: options.sessionId,
|
|
262
|
-
model: config.model,
|
|
263
|
-
}),
|
|
264
|
-
signal: AbortSignal.timeout(config.timeout),
|
|
265
|
-
});
|
|
266
|
-
if (!response.ok) {
|
|
267
|
-
const errorBody = await safeJsonParse(response);
|
|
268
|
-
throw new errors_js_1.KoineError(errorBody?.error || `HTTP ${response.status} ${response.statusText}`, errorBody?.code || "HTTP_ERROR", errorBody?.rawText);
|
|
269
|
-
}
|
|
270
|
-
const result = await safeJsonParse(response);
|
|
271
|
-
if (!result) {
|
|
272
|
-
throw new errors_js_1.KoineError("Invalid response from Koine gateway: expected JSON", "INVALID_RESPONSE");
|
|
273
|
-
}
|
|
274
|
-
// Validate the response against the Zod schema
|
|
275
|
-
const parseResult = options.schema.safeParse(result.object);
|
|
276
|
-
if (!parseResult.success) {
|
|
277
|
-
throw new errors_js_1.KoineError(`Response validation failed: ${parseResult.error.message}`, "VALIDATION_ERROR", result.rawText);
|
|
278
|
-
}
|
|
37
|
+
function createKoine(config) {
|
|
38
|
+
// Validate config once at creation time
|
|
39
|
+
(0, http_js_1.validateConfig)(config);
|
|
279
40
|
return {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
sessionId: result.sessionId,
|
|
41
|
+
generateText: (options) => (0, text_js_1.generateText)(config, options),
|
|
42
|
+
streamText: (options) => (0, index_js_1.streamText)(config, options),
|
|
43
|
+
generateObject: (options) => (0, object_js_1.generateObject)(config, options),
|
|
284
44
|
};
|
|
285
45
|
}
|
|
286
46
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAoFA,kCAUC;AA9FD,sDAAsD;AACtD,uCAA2C;AAC3C,2CAIqB;AAUc,+FAXlC,0BAAc,OAWkC;AATjD,gDAAuE;AAShD,2FATU,qBAAU,OASV;AARjC,uCAImB;AAIV,6FALR,sBAAY,OAKQ;AA4CrB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,WAAW,CAAC,MAAmB;IAC9C,wCAAwC;IACxC,IAAA,wBAAc,EAAC,MAAM,CAAC,CAAC;IAEvB,OAAO;QACN,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,sBAAY,EAAC,MAAM,EAAE,OAAO,CAAC;QACxD,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,qBAAU,EAAC,MAAM,EAAE,OAAO,CAAC;QACpD,cAAc,EAAE,CAAI,OAAiC,EAAE,EAAE,CACxD,IAAA,0BAAc,EAAC,MAAM,EAAE,OAAO,CAAC;KAChC,CAAC;AACH,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known error codes returned by the SDK and gateway.
|
|
3
|
+
*/
|
|
4
|
+
export type KoineErrorCode = "HTTP_ERROR" | "INVALID_RESPONSE" | "INVALID_CONFIG" | "VALIDATION_ERROR" | "STREAM_ERROR" | "SSE_PARSE_ERROR" | "NO_SESSION" | "NO_USAGE" | "NO_RESPONSE_BODY" | "TIMEOUT" | "NETWORK_ERROR" | "INVALID_PARAMS" | "AUTH_ERROR" | "UNAUTHORIZED" | "SERVER_ERROR" | "SCHEMA_ERROR" | "RATE_LIMITED" | "CONTEXT_OVERFLOW";
|
|
1
5
|
/**
|
|
2
6
|
* Custom error class for Koine client errors.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* try {
|
|
11
|
+
* await generateText(config, { prompt: 'Hello' });
|
|
12
|
+
* } catch (error) {
|
|
13
|
+
* if (error instanceof KoineError) {
|
|
14
|
+
* console.error(`[${error.code}]: ${error.message}`);
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
3
18
|
*/
|
|
4
19
|
export declare class KoineError extends Error {
|
|
5
|
-
code:
|
|
6
|
-
rawText?: string;
|
|
7
|
-
constructor(message: string, code:
|
|
20
|
+
readonly code: KoineErrorCode;
|
|
21
|
+
readonly rawText?: string;
|
|
22
|
+
constructor(message: string, code: KoineErrorCode, rawText?: string);
|
|
8
23
|
}
|
|
9
24
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACpC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,cAAc,GAEvB,YAAY,GACZ,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,GAClB,cAAc,GACd,iBAAiB,GACjB,YAAY,GACZ,UAAU,GACV,kBAAkB,GAClB,SAAS,GACT,eAAe,GAEf,gBAAgB,GAChB,YAAY,GACZ,cAAc,GACd,cAAc,GACd,cAAc,GACd,cAAc,GACd,kBAAkB,CAAC;AAEtB;;;;;;;;;;;;;GAaG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM;CAQnE"}
|
package/dist/errors.js
CHANGED
|
@@ -3,12 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.KoineError = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Custom error class for Koine client errors.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* try {
|
|
10
|
+
* await generateText(config, { prompt: 'Hello' });
|
|
11
|
+
* } catch (error) {
|
|
12
|
+
* if (error instanceof KoineError) {
|
|
13
|
+
* console.error(`[${error.code}]: ${error.message}`);
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
6
17
|
*/
|
|
7
18
|
class KoineError extends Error {
|
|
8
19
|
code;
|
|
9
20
|
rawText;
|
|
10
21
|
constructor(message, code, rawText) {
|
|
11
22
|
super(message);
|
|
23
|
+
// Fix prototype chain for proper instanceof checks in transpiled code
|
|
24
|
+
Object.setPrototypeOf(this, KoineError.prototype);
|
|
12
25
|
this.name = "KoineError";
|
|
13
26
|
this.code = code;
|
|
14
27
|
this.rawText = rawText;
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAyBA;;;;;;;;;;;;;GAaG;AACH,MAAa,UAAW,SAAQ,KAAK;IAC3B,IAAI,CAAiB;IACrB,OAAO,CAAU;IAE1B,YAAY,OAAe,EAAE,IAAoB,EAAE,OAAgB;QAClE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,sEAAsE;QACtE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAZD,gCAYC"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type KoineErrorCode } from "./errors.js";
|
|
2
|
+
import type { KoineConfig } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Known error codes for type-safe validation.
|
|
5
|
+
*/
|
|
6
|
+
export declare const KNOWN_ERROR_CODES: Set<KoineErrorCode>;
|
|
7
|
+
/**
|
|
8
|
+
* Coerces an API error code to a known KoineErrorCode.
|
|
9
|
+
* Falls back to the provided default if the code is unknown.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toErrorCode(code: string | undefined, fallback: KoineErrorCode): KoineErrorCode;
|
|
12
|
+
/**
|
|
13
|
+
* Validates config parameters before making requests.
|
|
14
|
+
* @throws {KoineError} with code 'INVALID_CONFIG' if config is invalid
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateConfig(config: KoineConfig): void;
|
|
17
|
+
/**
|
|
18
|
+
* Creates an AbortSignal that combines timeout with optional user signal.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createAbortSignal(timeout: number, userSignal?: AbortSignal): AbortSignal;
|
|
21
|
+
/**
|
|
22
|
+
* Wraps fetch errors in KoineError for consistent error handling.
|
|
23
|
+
*/
|
|
24
|
+
export declare function safeFetch(url: string, options: RequestInit, timeout: number): Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* Safely parses JSON from a response, handling non-JSON bodies gracefully.
|
|
27
|
+
*/
|
|
28
|
+
export declare function safeJsonParse<T>(response: Response): Promise<T | null>;
|
|
29
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,iBAAiB,qBAqB5B,CAAC;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,EAAE,cAAc,GACtB,cAAc,CAKhB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAUxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,WAAW,GACtB,WAAW,CAOb;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,QAAQ,CAAC,CAqBnB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAO5E"}
|