@arnilo/prism-provider-openai 0.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to @arnilo/prism-provider-openai will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - Added `LICENSE` (MIT) and `CHANGELOG.md`.
13
+ - Added npm package metadata: `license`, `repository`, `bugs`, `homepage`,
14
+ `keywords`, and `sideEffects`.
15
+
16
+ ### Changed
17
+
18
+ - `files` whitelist now explicitly excludes `dist/__tests__/` and
19
+ `dist/**/*.map` from published tarballs.
20
+ - Made `prism` a required peer dependency; it is no longer optional.
21
+
22
+ ## [0.0.1] - 2026-06-22
23
+
24
+ ### Added
25
+
26
+ - Initial release of @arnilo/prism-provider-openai.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Prism contributors
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,22 @@
1
+ # @arnilo/prism-provider-openai
2
+
3
+ OpenAI provider package for Prism.
4
+
5
+ ```ts
6
+ import { createOpenAIProviderPackage } from "@arnilo/prism-provider-openai";
7
+
8
+ api.registerProviderPackage(createOpenAIProviderPackage({ apiKey: "fake-openai-key" }));
9
+ ```
10
+
11
+ Exports:
12
+ - `createOpenAIProviderPackage()`
13
+ - `createOpenAIResponsesProvider()`
14
+ - `createOpenAICodexProvider()`
15
+ - `openAIModels`, `openAICodexModels`
16
+ - `createOpenAICodexOAuthProvider()`, `openAICodexOAuthProvider`
17
+
18
+ Security defaults:
19
+ - No network calls during import, setup, build, or default tests.
20
+ - No automatic environment, file, keychain, or shell credential lookup.
21
+ - API keys/access tokens are resolved per request from caller-supplied values or resolvers.
22
+ - Live tests must stay opt-in behind `PRISM_LIVE_PROVIDER_TESTS=1` plus fake-safe provider-specific env names.
@@ -0,0 +1,3 @@
1
+ import type { CacheRetention, ProviderRequestOptions } from "@arnilo/prism";
2
+ export declare function promptCacheKey(options: ProviderRequestOptions | undefined): string | undefined;
3
+ export declare function promptCacheRetention(options: ProviderRequestOptions | undefined): CacheRetention | undefined;
package/dist/cache.js ADDED
@@ -0,0 +1,8 @@
1
+ export function promptCacheKey(options) {
2
+ const key = options?.cacheKey ?? options?.sessionId;
3
+ return key ? key.slice(0, 64) : undefined;
4
+ }
5
+ export function promptCacheRetention(options) {
6
+ return options?.cacheRetention === "none" ? undefined : options?.cacheRetention;
7
+ }
8
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1,7 @@
1
+ import type { AIProvider, CredentialValueSource } from "@arnilo/prism";
2
+ import { type OpenAIResponsesProviderOptions } from "./responses.js";
3
+ export interface OpenAICodexProviderOptions extends Omit<OpenAIResponsesProviderOptions, "id" | "apiKey"> {
4
+ readonly id?: string;
5
+ readonly accessToken?: CredentialValueSource;
6
+ }
7
+ export declare function createOpenAICodexProvider(options?: OpenAICodexProviderOptions): AIProvider;
package/dist/codex.js ADDED
@@ -0,0 +1,12 @@
1
+ import { createOpenAIResponsesProvider } from "./responses.js";
2
+ export function createOpenAICodexProvider(options = {}) {
3
+ // ponytail: Codex subscription Responses endpoint is distinct from the plain
4
+ // API-key base URL; keep them separate so OAuth tokens never silently hit /v1.
5
+ return createOpenAIResponsesProvider({
6
+ id: options.id ?? "openai-codex",
7
+ baseUrl: options.baseUrl ?? "https://chatgpt.com/backend-api/codex",
8
+ apiKey: options.accessToken,
9
+ fetch: options.fetch,
10
+ });
11
+ }
12
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1,13 @@
1
+ import { type CredentialValueSource, type ProviderPackage } from "@arnilo/prism";
2
+ export interface OpenAIProviderPackageOptions {
3
+ readonly apiKey?: CredentialValueSource;
4
+ readonly codexAccessToken?: CredentialValueSource;
5
+ readonly fetch?: typeof fetch;
6
+ readonly baseUrl?: string;
7
+ readonly codexBaseUrl?: string;
8
+ }
9
+ export declare function createOpenAIProviderPackage(options?: OpenAIProviderPackageOptions): ProviderPackage;
10
+ export { createOpenAIResponsesProvider, type OpenAIResponsesProviderOptions } from "./responses.js";
11
+ export { createOpenAICodexProvider, type OpenAICodexProviderOptions } from "./codex.js";
12
+ export { openAIModels, openAICodexModels } from "./models.js";
13
+ export { createOpenAICodexOAuthProvider, openAICodexOAuthProvider, type OpenAICodexOAuthOptions, createPkceVerifier, computeS256Challenge } from "./oauth.js";
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ import { defineProviderPackage } from "@arnilo/prism";
2
+ import { createOpenAICodexProvider } from "./codex.js";
3
+ import { openAICodexModels, openAIModels } from "./models.js";
4
+ import { openAICodexOAuthProvider } from "./oauth.js";
5
+ import { createOpenAIResponsesProvider } from "./responses.js";
6
+ export function createOpenAIProviderPackage(options = {}) {
7
+ return defineProviderPackage({
8
+ name: "@arnilo/prism-provider-openai",
9
+ description: "OpenAI provider package for Prism.",
10
+ docs: { links: ["docs/providers/openai.md"] },
11
+ setup(api) {
12
+ api.registerProvider(createOpenAIResponsesProvider({ apiKey: options.apiKey, baseUrl: options.baseUrl, fetch: options.fetch }));
13
+ api.registerProvider(createOpenAICodexProvider({ accessToken: options.codexAccessToken, baseUrl: options.codexBaseUrl, fetch: options.fetch }));
14
+ for (const model of openAIModels)
15
+ api.registerModel(model);
16
+ for (const model of openAICodexModels)
17
+ api.registerModel(model);
18
+ api.registerAuthMethod({ kind: "api_key", provider: "openai", credentialName: "apiKey" });
19
+ api.registerAuthMethod({ kind: "oauth", provider: "openai-codex", oauth: openAICodexOAuthProvider });
20
+ },
21
+ });
22
+ }
23
+ export { createOpenAIResponsesProvider } from "./responses.js";
24
+ export { createOpenAICodexProvider } from "./codex.js";
25
+ export { openAIModels, openAICodexModels } from "./models.js";
26
+ export { createOpenAICodexOAuthProvider, openAICodexOAuthProvider, createPkceVerifier, computeS256Challenge } from "./oauth.js";
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,38 @@
1
+ export declare const openAIModels: readonly [{
2
+ readonly provider: "openai";
3
+ readonly model: "gpt-5.1";
4
+ readonly displayName: "GPT-5.1";
5
+ readonly capabilities: {
6
+ readonly input: readonly ["text", "image"];
7
+ readonly output: readonly ["text"];
8
+ readonly reasoning: true;
9
+ readonly tools: true;
10
+ readonly streaming: true;
11
+ };
12
+ readonly limits: {
13
+ readonly contextWindow: 400000;
14
+ readonly maxOutputTokens: 128000;
15
+ };
16
+ readonly compat: {
17
+ readonly api: "openai-responses";
18
+ };
19
+ }];
20
+ export declare const openAICodexModels: readonly [{
21
+ readonly provider: "openai-codex";
22
+ readonly model: "gpt-5.1-codex";
23
+ readonly displayName: "GPT-5.1 Codex";
24
+ readonly capabilities: {
25
+ readonly input: readonly ["text"];
26
+ readonly output: readonly ["text"];
27
+ readonly reasoning: true;
28
+ readonly tools: true;
29
+ readonly streaming: true;
30
+ };
31
+ readonly limits: {
32
+ readonly contextWindow: 400000;
33
+ readonly maxOutputTokens: 128000;
34
+ };
35
+ readonly compat: {
36
+ readonly api: "openai-codex-responses";
37
+ };
38
+ }];
package/dist/models.js ADDED
@@ -0,0 +1,21 @@
1
+ export const openAIModels = [
2
+ {
3
+ provider: "openai",
4
+ model: "gpt-5.1",
5
+ displayName: "GPT-5.1",
6
+ capabilities: { input: ["text", "image"], output: ["text"], reasoning: true, tools: true, streaming: true },
7
+ limits: { contextWindow: 400_000, maxOutputTokens: 128_000 },
8
+ compat: { api: "openai-responses" },
9
+ },
10
+ ];
11
+ export const openAICodexModels = [
12
+ {
13
+ provider: "openai-codex",
14
+ model: "gpt-5.1-codex",
15
+ displayName: "GPT-5.1 Codex",
16
+ capabilities: { input: ["text"], output: ["text"], reasoning: true, tools: true, streaming: true },
17
+ limits: { contextWindow: 400_000, maxOutputTokens: 128_000 },
18
+ compat: { api: "openai-codex-responses" },
19
+ },
20
+ ];
21
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1,19 @@
1
+ import type { OAuthProvider } from "@arnilo/prism";
2
+ export interface OpenAICodexOAuthOptions {
3
+ readonly clientId?: string;
4
+ readonly fetch?: typeof fetch;
5
+ readonly authorizeUrl?: string;
6
+ readonly tokenUrl?: string;
7
+ readonly deviceCodeUrl?: string;
8
+ readonly redirectUri?: string;
9
+ readonly scope?: string;
10
+ }
11
+ export declare const openAICodexOAuthProvider: OAuthProvider;
12
+ /**
13
+ * RFC 7636 PKCE code verifier: 43-128 chars from the unreserved set.
14
+ * base64url(32 random bytes) yields exactly 43 chars, all unreserved.
15
+ */
16
+ export declare function createPkceVerifier(bytes?: number): string;
17
+ /** S256 code challenge: base64url(SHA-256(verifier)). */
18
+ export declare function computeS256Challenge(verifier: string): string;
19
+ export declare function createOpenAICodexOAuthProvider(options?: OpenAICodexOAuthOptions): OAuthProvider;
package/dist/oauth.js ADDED
@@ -0,0 +1,94 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ export const openAICodexOAuthProvider = createOpenAICodexOAuthProvider();
3
+ const REDACTED = "[REDACTED]";
4
+ /**
5
+ * RFC 7636 PKCE code verifier: 43-128 chars from the unreserved set.
6
+ * base64url(32 random bytes) yields exactly 43 chars, all unreserved.
7
+ */
8
+ export function createPkceVerifier(bytes = 32) {
9
+ return randomBytes(bytes).toString("base64url");
10
+ }
11
+ /** S256 code challenge: base64url(SHA-256(verifier)). */
12
+ export function computeS256Challenge(verifier) {
13
+ return createHash("sha256").update(verifier).digest("base64url");
14
+ }
15
+ export function createOpenAICodexOAuthProvider(options = {}) {
16
+ const clientId = options.clientId ?? "prism-codex";
17
+ const fetchImpl = options.fetch ?? fetch;
18
+ const tokenUrl = options.tokenUrl ?? "https://auth.openai.com/oauth/token";
19
+ const authorizeUrl = options.authorizeUrl ?? "https://auth.openai.com/oauth/authorize";
20
+ const deviceCodeUrl = options.deviceCodeUrl ?? "https://auth.openai.com/oauth/device/code";
21
+ return {
22
+ id: "openai-codex",
23
+ async login(callbacks) {
24
+ if (callbacks?.onDeviceCode) {
25
+ return deviceLogin({ callbacks, clientId, fetchImpl, tokenUrl, deviceCodeUrl, scope: options.scope });
26
+ }
27
+ const verifier = createPkceVerifier();
28
+ const challenge = computeS256Challenge(verifier);
29
+ const params = new URLSearchParams({
30
+ client_id: clientId,
31
+ code_challenge: challenge,
32
+ code_challenge_method: "S256",
33
+ response_type: "code",
34
+ });
35
+ if (options.redirectUri)
36
+ params.set("redirect_uri", options.redirectUri);
37
+ if (options.scope)
38
+ params.set("scope", options.scope);
39
+ await callbacks?.onAuth?.(`${authorizeUrl}?${params}`);
40
+ const code = await callbacks?.onPrompt?.("OpenAI authorization code");
41
+ if (!code)
42
+ throw new Error("OpenAI authorization code was not provided");
43
+ return tokenRequest(fetchImpl, tokenUrl, {
44
+ grant_type: "authorization_code",
45
+ client_id: clientId,
46
+ code,
47
+ code_verifier: verifier,
48
+ ...(options.redirectUri ? { redirect_uri: options.redirectUri } : {}),
49
+ });
50
+ },
51
+ refresh(credentials) {
52
+ if (!credentials.refresh)
53
+ return credentials;
54
+ return tokenRequest(fetchImpl, tokenUrl, { grant_type: "refresh_token", client_id: clientId, refresh_token: credentials.refresh }, [credentials.access, credentials.refresh].filter((s) => Boolean(s)));
55
+ },
56
+ getCredential(credentials) {
57
+ return credentials.access ? { type: "bearer", value: credentials.access, metadata: { accountId: credentials.accountId, expires: credentials.expires } } : undefined;
58
+ },
59
+ };
60
+ }
61
+ async function deviceLogin(options) {
62
+ const body = { client_id: options.clientId };
63
+ if (options.scope)
64
+ body.scope = options.scope;
65
+ const response = await options.fetchImpl(options.deviceCodeUrl, {
66
+ method: "POST",
67
+ headers: { "content-type": "application/json" },
68
+ body: JSON.stringify(body),
69
+ });
70
+ if (!response.ok)
71
+ throw new Error(`OpenAI device code failed: ${response.status} ${await response.text()}`);
72
+ const json = await response.json();
73
+ await options.callbacks.onDeviceCode?.({ userCode: json.user_code, verificationUri: json.verification_uri, expiresAt: json.expires_in ? new Date(Date.now() + json.expires_in * 1000).toISOString() : undefined });
74
+ return tokenRequest(options.fetchImpl, options.tokenUrl, {
75
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
76
+ client_id: options.clientId,
77
+ device_code: json.device_code,
78
+ });
79
+ }
80
+ async function tokenRequest(fetchImpl, url, body, secrets = []) {
81
+ const response = await fetchImpl(url, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
82
+ if (!response.ok)
83
+ throw redact(new Error(`OpenAI token request failed: ${response.status} ${await response.text()}`), secrets);
84
+ const json = await response.json();
85
+ return { access: json.access_token, refresh: json.refresh_token, expires: json.expires_in ? Date.now() + json.expires_in * 1000 : undefined, accountId: json.account_id };
86
+ }
87
+ function redact(error, secrets) {
88
+ let message = error.message;
89
+ for (const secret of secrets)
90
+ if (secret)
91
+ message = message.split(secret).join(REDACTED);
92
+ return new Error(message);
93
+ }
94
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1,8 @@
1
+ import type { AIProvider, CredentialValueSource } from "@arnilo/prism";
2
+ export interface OpenAIResponsesProviderOptions {
3
+ readonly id?: string;
4
+ readonly baseUrl?: string;
5
+ readonly apiKey?: CredentialValueSource;
6
+ readonly fetch?: typeof fetch;
7
+ }
8
+ export declare function createOpenAIResponsesProvider(options?: OpenAIResponsesProviderOptions): AIProvider;
@@ -0,0 +1,155 @@
1
+ import { providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallContent } from "@arnilo/prism";
2
+ import { promptCacheKey, promptCacheRetention } from "./cache.js";
3
+ import { readSseData } from "./sse.js";
4
+ export function createOpenAIResponsesProvider(options = {}) {
5
+ const id = options.id ?? "openai";
6
+ return {
7
+ id,
8
+ async *generate(request) {
9
+ if (request.signal?.aborted)
10
+ throw request.signal.reason ?? new Error("aborted");
11
+ const token = await resolveCredentialValue(options.apiKey, { provider: id, name: "apiKey" });
12
+ const secrets = [token];
13
+ const tools = new Map();
14
+ let usage;
15
+ try {
16
+ const response = await (options.fetch ?? fetch)(`${(options.baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "")}/responses`, {
17
+ method: "POST",
18
+ headers: {
19
+ "content-type": "application/json",
20
+ ...request.options?.headers,
21
+ ...(token ? { authorization: `Bearer ${token}` } : {}),
22
+ ...(request.options?.sessionId ? { "x-client-request-id": request.options.sessionId } : {}),
23
+ },
24
+ body: JSON.stringify(toResponsesRequest(request)),
25
+ signal: request.signal,
26
+ });
27
+ if (!response.ok)
28
+ return yield providerError(new Error(`OpenAI request failed: ${response.status} ${await safeText(response)}`), secrets);
29
+ if (!response.body)
30
+ return yield providerError(new Error("OpenAI response had no body"), secrets);
31
+ for await (const data of readSseData(response.body)) {
32
+ if (data === "[DONE]")
33
+ break;
34
+ const event = JSON.parse(data);
35
+ if (typeof event.delta === "string" && event.type?.includes("output_text"))
36
+ yield providerTextDelta(event.delta);
37
+ if (typeof event.delta === "string" && event.type?.includes("reasoning"))
38
+ yield providerThinkingDelta(event.delta);
39
+ const tool = event.item ?? event.delta;
40
+ if (isToolDelta(tool)) {
41
+ const index = tool.index ?? 0;
42
+ const current = tools.get(index) ?? { argumentsText: "" };
43
+ current.id = tool.id ?? current.id;
44
+ current.name = tool.name ?? current.name;
45
+ current.argumentsText += tool.arguments ?? tool.arguments_delta ?? "";
46
+ tools.set(index, current);
47
+ yield providerToolCallDelta({ index, id: tool.id, name: tool.name, argumentsText: tool.arguments ?? tool.arguments_delta });
48
+ }
49
+ usage = toUsage(event.response?.usage ?? event.usage) ?? usage;
50
+ if (event.type?.endsWith("completed") && usage)
51
+ yield providerUsage(usage);
52
+ }
53
+ for (const call of tools.values())
54
+ if (call.id && call.name)
55
+ yield providerToolCall(toolCallContent(call.id, call.name, parseArgs(call.argumentsText)));
56
+ yield providerDone(usage);
57
+ }
58
+ catch (error) {
59
+ yield providerError(error, secrets);
60
+ }
61
+ },
62
+ };
63
+ }
64
+ function toResponsesRequest(request) {
65
+ const payload = {
66
+ model: request.model.model,
67
+ input: request.messages.map((message) => toInputMessage(message, request.model.capabilities ?? {})),
68
+ tools: request.tools?.map(toTool),
69
+ stream: true,
70
+ store: false,
71
+ prompt_cache_key: promptCacheKey(request.options),
72
+ prompt_cache_retention: promptCacheRetention(request.options),
73
+ ...request.model.parameters,
74
+ ...(request.options?.compat ?? {}),
75
+ ...(request.options?.extra ?? {}),
76
+ };
77
+ return clean(payload);
78
+ }
79
+ function toInputMessage(message, capabilities = {}) {
80
+ if (message.role === "tool") {
81
+ const result = message.content.find((part) => part.type === "tool_result");
82
+ return clean({
83
+ type: "function_call_output",
84
+ call_id: result?.toolCallId ?? "",
85
+ output: result ? JSON.stringify(result.result ?? result.error ?? null) : "",
86
+ });
87
+ }
88
+ const items = [];
89
+ for (const part of message.content) {
90
+ if (part.type === "text" || part.type === "thinking") {
91
+ items.push({ type: "input_text", text: part.text });
92
+ }
93
+ else if (part.type === "image") {
94
+ if (!capabilities.input?.includes("image")) {
95
+ throw new Error(`OpenAI Responses request includes image but model does not declare image input capability`);
96
+ }
97
+ items.push(toResponsesImage(part));
98
+ }
99
+ else if (part.type === "tool_call") {
100
+ items.push({
101
+ type: "function_call",
102
+ id: part.id,
103
+ name: part.name,
104
+ arguments: JSON.stringify(part.arguments),
105
+ });
106
+ }
107
+ else if (part.type === "tool_result") {
108
+ throw new Error("OpenAI Responses tool_result blocks must appear in role=tool messages");
109
+ }
110
+ }
111
+ if (message.role === "assistant") {
112
+ return clean({ role: "assistant", content: items });
113
+ }
114
+ return clean({ role: message.role, content: items });
115
+ }
116
+ function toResponsesImage(part) {
117
+ const url = part.url ?? (part.data ? `data:${part.mimeType ?? "image/png"};base64,${part.data}` : undefined);
118
+ if (!url)
119
+ throw new Error("OpenAI Responses image block missing url or data");
120
+ return { type: "input_image", image_url: url };
121
+ }
122
+ function toTool(tool) {
123
+ return clean({ type: "function", name: tool.name, description: tool.description, parameters: tool.parameters ?? { type: "object" } });
124
+ }
125
+ function toUsage(usage) {
126
+ if (!usage)
127
+ return undefined;
128
+ return {
129
+ inputTokens: usage.input_tokens,
130
+ outputTokens: usage.output_tokens,
131
+ totalTokens: usage.total_tokens,
132
+ cacheReadTokens: usage.input_tokens_details?.cached_tokens,
133
+ };
134
+ }
135
+ function isToolDelta(value) {
136
+ return !!value && typeof value === "object" && ("arguments" in value || "arguments_delta" in value) && ("name" in value || "id" in value);
137
+ }
138
+ function parseArgs(text) {
139
+ if (!text)
140
+ return {};
141
+ const parsed = JSON.parse(text);
142
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
143
+ }
144
+ function clean(value) {
145
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
146
+ }
147
+ async function safeText(response) {
148
+ try {
149
+ return await response.text();
150
+ }
151
+ catch {
152
+ return "";
153
+ }
154
+ }
155
+ //# sourceMappingURL=responses.js.map
package/dist/sse.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function readSseData(body: ReadableStream<Uint8Array>): AsyncIterable<string>;
package/dist/sse.js ADDED
@@ -0,0 +1,24 @@
1
+ export async function* readSseData(body) {
2
+ const reader = body.getReader();
3
+ const decoder = new TextDecoder();
4
+ let buffer = "";
5
+ while (true) {
6
+ const { done, value } = await reader.read();
7
+ if (done)
8
+ break;
9
+ buffer += decoder.decode(value, { stream: true });
10
+ const parts = buffer.split(/\r?\n\r?\n/);
11
+ buffer = parts.pop() ?? "";
12
+ for (const part of parts)
13
+ yield* eventData(part);
14
+ }
15
+ buffer += decoder.decode();
16
+ if (buffer)
17
+ yield* eventData(buffer);
18
+ }
19
+ function* eventData(event) {
20
+ const lines = event.split(/\r?\n/).filter((line) => line.startsWith("data:"));
21
+ if (lines.length)
22
+ yield lines.map((line) => line.slice(5).trimStart()).join("\n").trim();
23
+ }
24
+ //# sourceMappingURL=sse.js.map
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@arnilo/prism-provider-openai",
3
+ "version": "0.0.1",
4
+ "description": "OpenAI provider package for Prism.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "!dist/__tests__",
17
+ "!dist/**/*.map",
18
+ "README.md",
19
+ "CHANGELOG.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.json",
23
+ "typecheck": "tsc -p tsconfig.json --noEmit",
24
+ "test": "node --test dist/__tests__/*.test.js",
25
+ "pack:dry-run": "npm pack --dry-run"
26
+ },
27
+ "peerDependencies": {
28
+ "@arnilo/prism": "0.0.1"
29
+ },
30
+ "devDependencies": {
31
+ "@arnilo/prism": "file:../.."
32
+ },
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/ashiqrniloy/prism.git",
40
+ "directory": "packages/provider-openai"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/ashiqrniloy/prism/issues"
44
+ },
45
+ "homepage": "https://github.com/ashiqrniloy/prism/tree/main/packages/provider-openai#readme",
46
+ "keywords": [
47
+ "prism",
48
+ "provider",
49
+ "openai",
50
+ "agent",
51
+ "llm"
52
+ ],
53
+ "sideEffects": false,
54
+ "publishConfig": {
55
+ "access": "public"
56
+ }
57
+ }