juneau 0.1.0 → 0.1.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/README.md +316 -118
- package/dist/adapters/createFetchStreamAdapter.d.ts +88 -0
- package/dist/adapters/createFetchStreamAdapter.d.ts.map +1 -0
- package/dist/adapters/createSseAdapter.d.ts +94 -0
- package/dist/adapters/createSseAdapter.d.ts.map +1 -0
- package/dist/index.cjs +39 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3006 -2862
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { AiBackendAdapter, AiAdapterInput, AiStreamEvent } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* How to map a raw text chunk from the response body to Juneau stream events.
|
|
4
|
+
*
|
|
5
|
+
* Return an array — a chunk may produce one event, multiple, or none (empty array to skip).
|
|
6
|
+
* The chunk is whatever the server sent — could be a full JSON line, a partial one,
|
|
7
|
+
* or plain text depending on your backend.
|
|
8
|
+
*/
|
|
9
|
+
export type FetchChunkParser = (chunk: string) => AiStreamEvent[];
|
|
10
|
+
/**
|
|
11
|
+
* Options for createFetchStreamAdapter.
|
|
12
|
+
*/
|
|
13
|
+
export type FetchStreamAdapterOptions = {
|
|
14
|
+
/**
|
|
15
|
+
* HTTP method. Defaults to 'POST'.
|
|
16
|
+
*/
|
|
17
|
+
method?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Static headers merged with Content-Type. Use for auth tokens etc.
|
|
20
|
+
* For dynamic headers (e.g. per-request auth), use getHeaders instead.
|
|
21
|
+
*
|
|
22
|
+
* @example { Authorization: 'Bearer sk-...' }
|
|
23
|
+
*/
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Dynamic headers — called before every request with the current adapter input.
|
|
27
|
+
* Merged on top of `headers`. Use this when the token is fetched at runtime.
|
|
28
|
+
*/
|
|
29
|
+
getHeaders?: (input: AiAdapterInput) => Record<string, string> | Promise<Record<string, string>>;
|
|
30
|
+
/**
|
|
31
|
+
* Override the request body. By default sends `{ messages, context }`.
|
|
32
|
+
* Return anything JSON-serialisable.
|
|
33
|
+
*/
|
|
34
|
+
getBody?: (input: AiAdapterInput) => unknown;
|
|
35
|
+
/**
|
|
36
|
+
* How to parse each chunk from the response stream into Juneau events.
|
|
37
|
+
*
|
|
38
|
+
* Defaults to a newline-delimited JSON (NDJSON) parser that expects each
|
|
39
|
+
* line to be either `{ text: "..." }` or `{ done: true }`.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Plain text streaming — treat every chunk as raw text:
|
|
43
|
+
* parseChunk: (chunk) => chunk ? [{ type: 'text', text: chunk }] : []
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Custom JSON lines format:
|
|
47
|
+
* parseChunk: (chunk) => {
|
|
48
|
+
* try {
|
|
49
|
+
* const json = JSON.parse(chunk);
|
|
50
|
+
* if (json.error) return [{ type: 'error', message: json.error }];
|
|
51
|
+
* if (json.done) return [{ type: 'done' }];
|
|
52
|
+
* if (json.delta) return [{ type: 'text', text: json.delta }];
|
|
53
|
+
* return [];
|
|
54
|
+
* } catch { return []; }
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
parseChunk?: FetchChunkParser;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Creates an adapter that connects to a **raw chunked HTTP streaming** endpoint —
|
|
61
|
+
* for backends that stream newline-delimited JSON (NDJSON) or plain text,
|
|
62
|
+
* rather than SSE.
|
|
63
|
+
*
|
|
64
|
+
* Use `createSseAdapter` instead if your backend streams Server-Sent Events
|
|
65
|
+
* (the format used by OpenAI, Anthropic, and most AI APIs).
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // NDJSON backend streaming { text: "..." } lines — works with zero config:
|
|
69
|
+
* const adapter = createFetchStreamAdapter('/api/chat');
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Plain text streaming (each chunk is raw text, no JSON):
|
|
73
|
+
* const adapter = createFetchStreamAdapter('/api/chat', {
|
|
74
|
+
* parseChunk: (chunk) => chunk ? [{ type: 'text', text: chunk }] : [],
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Custom body + auth:
|
|
79
|
+
* const adapter = createFetchStreamAdapter('/api/chat', {
|
|
80
|
+
* getHeaders: async () => ({ Authorization: `Bearer ${await getToken()}` }),
|
|
81
|
+
* getBody: ({ messages, context }) => ({
|
|
82
|
+
* history: messages,
|
|
83
|
+
* model: context?.model ?? 'default',
|
|
84
|
+
* }),
|
|
85
|
+
* });
|
|
86
|
+
*/
|
|
87
|
+
export declare function createFetchStreamAdapter(url: string, options?: FetchStreamAdapterOptions): AiBackendAdapter;
|
|
88
|
+
//# sourceMappingURL=createFetchStreamAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createFetchStreamAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/createFetchStreamAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAErF;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAEjG;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC;IAE7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,yBAA8B,GACtC,gBAAgB,CAyClB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { AiBackendAdapter, AiAdapterInput, AiStreamEvent } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* How to map a parsed SSE data payload to Juneau stream events.
|
|
4
|
+
*
|
|
5
|
+
* Return an array — most lines produce one event, but you can return multiple
|
|
6
|
+
* or an empty array to skip a line entirely.
|
|
7
|
+
*/
|
|
8
|
+
export type SseEventParser = (data: string) => AiStreamEvent[];
|
|
9
|
+
/**
|
|
10
|
+
* Options for createSseAdapter.
|
|
11
|
+
*/
|
|
12
|
+
export type SseAdapterOptions = {
|
|
13
|
+
/**
|
|
14
|
+
* HTTP method. Defaults to 'POST'.
|
|
15
|
+
*/
|
|
16
|
+
method?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Static headers merged with Content-Type. Use for auth tokens etc.
|
|
19
|
+
* For dynamic headers (e.g. per-request auth), use getHeaders instead.
|
|
20
|
+
*
|
|
21
|
+
* @example { Authorization: 'Bearer sk-...' }
|
|
22
|
+
*/
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Dynamic headers — called before every request with the current adapter input.
|
|
26
|
+
* Merged on top of `headers`. Use this when the token is fetched at runtime.
|
|
27
|
+
*/
|
|
28
|
+
getHeaders?: (input: AiAdapterInput) => Record<string, string> | Promise<Record<string, string>>;
|
|
29
|
+
/**
|
|
30
|
+
* Override the request body. By default sends `{ messages, context }`.
|
|
31
|
+
* Return anything JSON-serialisable.
|
|
32
|
+
*/
|
|
33
|
+
getBody?: (input: AiAdapterInput) => unknown;
|
|
34
|
+
/**
|
|
35
|
+
* Custom SSE line parser. Receives the raw string after `data: ` and returns
|
|
36
|
+
* zero or more Juneau stream events.
|
|
37
|
+
*
|
|
38
|
+
* Defaults to an OpenAI-compatible parser that reads
|
|
39
|
+
* `choices[0].delta.content` and handles `[DONE]`.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // For a backend that streams { text: "..." } JSON lines:
|
|
43
|
+
* parseEvent: (data) => {
|
|
44
|
+
* const json = JSON.parse(data);
|
|
45
|
+
* return json.text ? [{ type: 'text', text: json.text }] : [];
|
|
46
|
+
* }
|
|
47
|
+
*/
|
|
48
|
+
parseEvent?: SseEventParser;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Creates an adapter that connects to a **Server-Sent Events (SSE)** streaming
|
|
52
|
+
* endpoint — the format used by OpenAI, Anthropic, and most AI backend proxies.
|
|
53
|
+
*
|
|
54
|
+
* The default parser understands OpenAI's streaming format out of the box.
|
|
55
|
+
* Override `parseEvent` for any other SSE schema.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // OpenAI-compatible backend proxy — works with zero configuration:
|
|
59
|
+
* const adapter = createSseAdapter('/api/chat');
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // With auth header:
|
|
63
|
+
* const adapter = createSseAdapter('/api/chat', {
|
|
64
|
+
* getHeaders: async () => ({
|
|
65
|
+
* Authorization: `Bearer ${await getToken()}`,
|
|
66
|
+
* }),
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Custom body shape:
|
|
71
|
+
* const adapter = createSseAdapter('/api/chat', {
|
|
72
|
+
* getBody: ({ messages, context }) => ({
|
|
73
|
+
* messages,
|
|
74
|
+
* model: 'gpt-4o',
|
|
75
|
+
* stream: true,
|
|
76
|
+
* ...(context?.systemPrompt ? { system: context.systemPrompt } : {}),
|
|
77
|
+
* }),
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Custom SSE schema (backend streams { text: "..." }):
|
|
82
|
+
* const adapter = createSseAdapter('/api/chat', {
|
|
83
|
+
* parseEvent: (data) => {
|
|
84
|
+
* try {
|
|
85
|
+
* const json = JSON.parse(data);
|
|
86
|
+
* return json.text ? [{ type: 'text', text: json.text }] : [];
|
|
87
|
+
* } catch {
|
|
88
|
+
* return [];
|
|
89
|
+
* }
|
|
90
|
+
* },
|
|
91
|
+
* });
|
|
92
|
+
*/
|
|
93
|
+
export declare function createSseAdapter(url: string, options?: SseAdapterOptions): AiBackendAdapter;
|
|
94
|
+
//# sourceMappingURL=createSseAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSseAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/createSseAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAErF;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAEjG;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC;IAE7C;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAyC/F"}
|