@byoky/core 0.2.0 → 0.3.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/dist/index.d.cts CHANGED
@@ -12,6 +12,7 @@ interface OAuthConfig {
12
12
  authorizationUrl: string;
13
13
  tokenUrl: string;
14
14
  scopes: string[];
15
+ extraAuthParams?: Record<string, string>;
15
16
  }
16
17
  interface CredentialBase {
17
18
  id: string;
@@ -99,13 +100,23 @@ interface ProxyResponseError {
99
100
  message: string;
100
101
  };
101
102
  }
102
- type MessageType = 'BYOKY_CONNECT_REQUEST' | 'BYOKY_CONNECT_RESPONSE' | 'BYOKY_DISCONNECT' | 'BYOKY_PROXY_REQUEST' | 'BYOKY_PROXY_RESPONSE_META' | 'BYOKY_PROXY_RESPONSE_CHUNK' | 'BYOKY_PROXY_RESPONSE_DONE' | 'BYOKY_PROXY_RESPONSE_ERROR' | 'BYOKY_ERROR';
103
+ type MessageType = 'BYOKY_CONNECT_REQUEST' | 'BYOKY_CONNECT_RESPONSE' | 'BYOKY_DISCONNECT' | 'BYOKY_PROXY_REQUEST' | 'BYOKY_PROXY_RESPONSE_META' | 'BYOKY_PROXY_RESPONSE_CHUNK' | 'BYOKY_PROXY_RESPONSE_DONE' | 'BYOKY_PROXY_RESPONSE_ERROR' | 'BYOKY_SESSION_STATUS' | 'BYOKY_SESSION_STATUS_RESPONSE' | 'BYOKY_SESSION_USAGE' | 'BYOKY_SESSION_USAGE_RESPONSE' | 'BYOKY_SESSION_REVOKED' | 'BYOKY_ERROR';
103
104
  interface ByokyMessage {
104
105
  type: MessageType;
105
106
  id: string;
106
107
  requestId?: string;
107
108
  payload: unknown;
108
109
  }
110
+ interface SessionUsage {
111
+ requests: number;
112
+ inputTokens: number;
113
+ outputTokens: number;
114
+ byProvider: Record<string, {
115
+ requests: number;
116
+ inputTokens: number;
117
+ outputTokens: number;
118
+ }>;
119
+ }
109
120
  declare enum ByokyErrorCode {
110
121
  WALLET_NOT_INSTALLED = "WALLET_NOT_INSTALLED",
111
122
  USER_REJECTED = "USER_REJECTED",
@@ -116,6 +127,8 @@ declare enum ByokyErrorCode {
116
127
  INVALID_KEY = "INVALID_KEY",
117
128
  TOKEN_EXPIRED = "TOKEN_EXPIRED",
118
129
  PROXY_ERROR = "PROXY_ERROR",
130
+ RELAY_CONNECTION_FAILED = "RELAY_CONNECTION_FAILED",
131
+ RELAY_DISCONNECTED = "RELAY_DISCONNECTED",
119
132
  UNKNOWN = "UNKNOWN"
120
133
  }
121
134
  interface RequestLogEntry {
@@ -128,6 +141,9 @@ interface RequestLogEntry {
128
141
  status: number;
129
142
  timestamp: number;
130
143
  error?: string;
144
+ inputTokens?: number;
145
+ outputTokens?: number;
146
+ model?: string;
131
147
  }
132
148
  interface PendingApproval {
133
149
  id: string;
@@ -136,6 +152,15 @@ interface PendingApproval {
136
152
  providers: ProviderRequirement[];
137
153
  timestamp: number;
138
154
  }
155
+ interface TrustedSite {
156
+ origin: string;
157
+ trustedAt: number;
158
+ }
159
+ interface TokenAllowance {
160
+ origin: string;
161
+ totalLimit?: number;
162
+ providerLimits?: Record<string, number>;
163
+ }
139
164
 
140
165
  declare function deriveKey(password: string, salt: Uint8Array): Promise<CryptoKey>;
141
166
  declare function encrypt(plaintext: string, password: string): Promise<string>;
@@ -156,6 +181,8 @@ declare class ByokyError extends Error {
156
181
  static quotaExceeded(providerId: string): ByokyError;
157
182
  static invalidKey(providerId: string): ByokyError;
158
183
  static tokenExpired(providerId: string): ByokyError;
184
+ static relayConnectionFailed(reason?: string): ByokyError;
185
+ static relayDisconnected(): ByokyError;
159
186
  }
160
187
 
161
188
  declare const BYOKY_PROVIDER_KEY = "__byoky__";
@@ -170,4 +197,124 @@ declare const PROVIDERS: Record<string, ProviderConfig>;
170
197
  declare function getProvider(id: string): ProviderConfig | undefined;
171
198
  declare function getProviderIds(): string[];
172
199
 
173
- export { type ApiKeyCredential, type AuthMethod, BYOKY_MESSAGE_PREFIX, BYOKY_PROVIDER_KEY, ByokyError, ByokyErrorCode, type ByokyMessage, type ConnectRequest, type ConnectResponse, type Credential, type CredentialBase, type CredentialMeta, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RequestLogEntry, type Session, type SessionProvider, createConnectRequest, createConnectResponse, createErrorMessage, createMessage, decrypt, deriveKey, encrypt, getProvider, getProviderIds, hashPassword, isByokyMessage, maskKey, verifyPassword };
200
+ /** Minimal WebSocket interface compatible with browser WebSocket and `ws` library. */
201
+ interface WebSocketLike {
202
+ readonly readyState: number;
203
+ send(data: string): void;
204
+ close(code?: number, reason?: string): void;
205
+ onopen: ((event: unknown) => void) | null;
206
+ onmessage: ((event: {
207
+ data: unknown;
208
+ }) => void) | null;
209
+ onclose: ((event: {
210
+ code: number;
211
+ reason: string;
212
+ }) => void) | null;
213
+ onerror: ((event: unknown) => void) | null;
214
+ }
215
+ declare const WS_READY_STATE: {
216
+ readonly CONNECTING: 0;
217
+ readonly OPEN: 1;
218
+ readonly CLOSING: 2;
219
+ readonly CLOSED: 3;
220
+ };
221
+ interface RelayHello {
222
+ type: 'relay:hello';
223
+ sessionId: string;
224
+ providers: Record<string, {
225
+ available: boolean;
226
+ authMethod: AuthMethod;
227
+ }>;
228
+ }
229
+ interface RelayRequest {
230
+ type: 'relay:request';
231
+ requestId: string;
232
+ providerId: string;
233
+ url: string;
234
+ method: string;
235
+ headers: Record<string, string>;
236
+ body?: string;
237
+ }
238
+ interface RelayResponseMeta {
239
+ type: 'relay:response:meta';
240
+ requestId: string;
241
+ status: number;
242
+ statusText: string;
243
+ headers: Record<string, string>;
244
+ }
245
+ interface RelayResponseChunk {
246
+ type: 'relay:response:chunk';
247
+ requestId: string;
248
+ chunk: string;
249
+ }
250
+ interface RelayResponseDone {
251
+ type: 'relay:response:done';
252
+ requestId: string;
253
+ }
254
+ interface RelayResponseError {
255
+ type: 'relay:response:error';
256
+ requestId: string;
257
+ error: {
258
+ code: string;
259
+ message: string;
260
+ };
261
+ }
262
+ interface RelayPing {
263
+ type: 'relay:ping';
264
+ ts: number;
265
+ }
266
+ interface RelayPong {
267
+ type: 'relay:pong';
268
+ ts: number;
269
+ }
270
+ type RelayMessage = RelayHello | RelayRequest | RelayResponseMeta | RelayResponseChunk | RelayResponseDone | RelayResponseError | RelayPing | RelayPong;
271
+ declare function parseRelayMessage(data: unknown): RelayMessage | null;
272
+ declare function sendRelayMessage(ws: WebSocketLike, msg: RelayMessage): void;
273
+
274
+ interface PasswordStrength {
275
+ score: 0 | 1 | 2 | 3 | 4;
276
+ label: 'Too weak' | 'Weak' | 'Fair' | 'Strong' | 'Very strong';
277
+ feedback: string[];
278
+ }
279
+ declare function checkPasswordStrength(password: string): PasswordStrength;
280
+ declare const MIN_PASSWORD_LENGTH = 12;
281
+
282
+ /**
283
+ * Validate that a proxy request URL targets the registered provider's base URL.
284
+ * Prevents API key exfiltration by rejecting requests to arbitrary domains.
285
+ */
286
+ declare function validateProxyUrl(providerId: string, url: string): boolean;
287
+ /**
288
+ * Build the real auth headers for a provider API request.
289
+ * Strips any fake session-key headers and injects the real API key.
290
+ */
291
+ declare function buildHeaders(providerId: string, requestHeaders: Record<string, string>, apiKey: string, authMethod?: string): Record<string, string>;
292
+ /**
293
+ * Parse the model name from a request body (JSON).
294
+ */
295
+ declare function parseModel(body?: string): string | undefined;
296
+ /**
297
+ * Parse token usage from a provider API response body.
298
+ * Handles both regular JSON responses and SSE streaming responses.
299
+ */
300
+ declare function parseUsage(providerId: string, body: string): {
301
+ inputTokens: number;
302
+ outputTokens: number;
303
+ } | undefined;
304
+ /**
305
+ * Extract token usage from a parsed provider response object.
306
+ */
307
+ declare function extractUsageFromParsed(providerId: string, parsed: Record<string, unknown>): {
308
+ inputTokens: number;
309
+ outputTokens: number;
310
+ } | undefined;
311
+ /**
312
+ * Check whether a request is allowed given token allowances and usage history.
313
+ * Pure computation — no storage access.
314
+ */
315
+ declare function computeAllowanceCheck(allowance: TokenAllowance | undefined, entries: Pick<RequestLogEntry, 'providerId' | 'inputTokens' | 'outputTokens'>[], providerId: string): {
316
+ allowed: boolean;
317
+ reason?: string;
318
+ };
319
+
320
+ export { type ApiKeyCredential, type AuthMethod, BYOKY_MESSAGE_PREFIX, BYOKY_PROVIDER_KEY, ByokyError, ByokyErrorCode, type ByokyMessage, type ConnectRequest, type ConnectResponse, type Credential, type CredentialBase, type CredentialMeta, MIN_PASSWORD_LENGTH, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PasswordStrength, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RelayHello, type RelayMessage, type RelayPing, type RelayPong, type RelayRequest, type RelayResponseChunk, type RelayResponseDone, type RelayResponseError, type RelayResponseMeta, type RequestLogEntry, type Session, type SessionProvider, type SessionUsage, type TokenAllowance, type TrustedSite, WS_READY_STATE, type WebSocketLike, buildHeaders, checkPasswordStrength, computeAllowanceCheck, createConnectRequest, createConnectResponse, createErrorMessage, createMessage, decrypt, deriveKey, encrypt, extractUsageFromParsed, getProvider, getProviderIds, hashPassword, isByokyMessage, maskKey, parseModel, parseRelayMessage, parseUsage, sendRelayMessage, validateProxyUrl, verifyPassword };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ interface OAuthConfig {
12
12
  authorizationUrl: string;
13
13
  tokenUrl: string;
14
14
  scopes: string[];
15
+ extraAuthParams?: Record<string, string>;
15
16
  }
16
17
  interface CredentialBase {
17
18
  id: string;
@@ -99,13 +100,23 @@ interface ProxyResponseError {
99
100
  message: string;
100
101
  };
101
102
  }
102
- type MessageType = 'BYOKY_CONNECT_REQUEST' | 'BYOKY_CONNECT_RESPONSE' | 'BYOKY_DISCONNECT' | 'BYOKY_PROXY_REQUEST' | 'BYOKY_PROXY_RESPONSE_META' | 'BYOKY_PROXY_RESPONSE_CHUNK' | 'BYOKY_PROXY_RESPONSE_DONE' | 'BYOKY_PROXY_RESPONSE_ERROR' | 'BYOKY_ERROR';
103
+ type MessageType = 'BYOKY_CONNECT_REQUEST' | 'BYOKY_CONNECT_RESPONSE' | 'BYOKY_DISCONNECT' | 'BYOKY_PROXY_REQUEST' | 'BYOKY_PROXY_RESPONSE_META' | 'BYOKY_PROXY_RESPONSE_CHUNK' | 'BYOKY_PROXY_RESPONSE_DONE' | 'BYOKY_PROXY_RESPONSE_ERROR' | 'BYOKY_SESSION_STATUS' | 'BYOKY_SESSION_STATUS_RESPONSE' | 'BYOKY_SESSION_USAGE' | 'BYOKY_SESSION_USAGE_RESPONSE' | 'BYOKY_SESSION_REVOKED' | 'BYOKY_ERROR';
103
104
  interface ByokyMessage {
104
105
  type: MessageType;
105
106
  id: string;
106
107
  requestId?: string;
107
108
  payload: unknown;
108
109
  }
110
+ interface SessionUsage {
111
+ requests: number;
112
+ inputTokens: number;
113
+ outputTokens: number;
114
+ byProvider: Record<string, {
115
+ requests: number;
116
+ inputTokens: number;
117
+ outputTokens: number;
118
+ }>;
119
+ }
109
120
  declare enum ByokyErrorCode {
110
121
  WALLET_NOT_INSTALLED = "WALLET_NOT_INSTALLED",
111
122
  USER_REJECTED = "USER_REJECTED",
@@ -116,6 +127,8 @@ declare enum ByokyErrorCode {
116
127
  INVALID_KEY = "INVALID_KEY",
117
128
  TOKEN_EXPIRED = "TOKEN_EXPIRED",
118
129
  PROXY_ERROR = "PROXY_ERROR",
130
+ RELAY_CONNECTION_FAILED = "RELAY_CONNECTION_FAILED",
131
+ RELAY_DISCONNECTED = "RELAY_DISCONNECTED",
119
132
  UNKNOWN = "UNKNOWN"
120
133
  }
121
134
  interface RequestLogEntry {
@@ -128,6 +141,9 @@ interface RequestLogEntry {
128
141
  status: number;
129
142
  timestamp: number;
130
143
  error?: string;
144
+ inputTokens?: number;
145
+ outputTokens?: number;
146
+ model?: string;
131
147
  }
132
148
  interface PendingApproval {
133
149
  id: string;
@@ -136,6 +152,15 @@ interface PendingApproval {
136
152
  providers: ProviderRequirement[];
137
153
  timestamp: number;
138
154
  }
155
+ interface TrustedSite {
156
+ origin: string;
157
+ trustedAt: number;
158
+ }
159
+ interface TokenAllowance {
160
+ origin: string;
161
+ totalLimit?: number;
162
+ providerLimits?: Record<string, number>;
163
+ }
139
164
 
140
165
  declare function deriveKey(password: string, salt: Uint8Array): Promise<CryptoKey>;
141
166
  declare function encrypt(plaintext: string, password: string): Promise<string>;
@@ -156,6 +181,8 @@ declare class ByokyError extends Error {
156
181
  static quotaExceeded(providerId: string): ByokyError;
157
182
  static invalidKey(providerId: string): ByokyError;
158
183
  static tokenExpired(providerId: string): ByokyError;
184
+ static relayConnectionFailed(reason?: string): ByokyError;
185
+ static relayDisconnected(): ByokyError;
159
186
  }
160
187
 
161
188
  declare const BYOKY_PROVIDER_KEY = "__byoky__";
@@ -170,4 +197,124 @@ declare const PROVIDERS: Record<string, ProviderConfig>;
170
197
  declare function getProvider(id: string): ProviderConfig | undefined;
171
198
  declare function getProviderIds(): string[];
172
199
 
173
- export { type ApiKeyCredential, type AuthMethod, BYOKY_MESSAGE_PREFIX, BYOKY_PROVIDER_KEY, ByokyError, ByokyErrorCode, type ByokyMessage, type ConnectRequest, type ConnectResponse, type Credential, type CredentialBase, type CredentialMeta, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RequestLogEntry, type Session, type SessionProvider, createConnectRequest, createConnectResponse, createErrorMessage, createMessage, decrypt, deriveKey, encrypt, getProvider, getProviderIds, hashPassword, isByokyMessage, maskKey, verifyPassword };
200
+ /** Minimal WebSocket interface compatible with browser WebSocket and `ws` library. */
201
+ interface WebSocketLike {
202
+ readonly readyState: number;
203
+ send(data: string): void;
204
+ close(code?: number, reason?: string): void;
205
+ onopen: ((event: unknown) => void) | null;
206
+ onmessage: ((event: {
207
+ data: unknown;
208
+ }) => void) | null;
209
+ onclose: ((event: {
210
+ code: number;
211
+ reason: string;
212
+ }) => void) | null;
213
+ onerror: ((event: unknown) => void) | null;
214
+ }
215
+ declare const WS_READY_STATE: {
216
+ readonly CONNECTING: 0;
217
+ readonly OPEN: 1;
218
+ readonly CLOSING: 2;
219
+ readonly CLOSED: 3;
220
+ };
221
+ interface RelayHello {
222
+ type: 'relay:hello';
223
+ sessionId: string;
224
+ providers: Record<string, {
225
+ available: boolean;
226
+ authMethod: AuthMethod;
227
+ }>;
228
+ }
229
+ interface RelayRequest {
230
+ type: 'relay:request';
231
+ requestId: string;
232
+ providerId: string;
233
+ url: string;
234
+ method: string;
235
+ headers: Record<string, string>;
236
+ body?: string;
237
+ }
238
+ interface RelayResponseMeta {
239
+ type: 'relay:response:meta';
240
+ requestId: string;
241
+ status: number;
242
+ statusText: string;
243
+ headers: Record<string, string>;
244
+ }
245
+ interface RelayResponseChunk {
246
+ type: 'relay:response:chunk';
247
+ requestId: string;
248
+ chunk: string;
249
+ }
250
+ interface RelayResponseDone {
251
+ type: 'relay:response:done';
252
+ requestId: string;
253
+ }
254
+ interface RelayResponseError {
255
+ type: 'relay:response:error';
256
+ requestId: string;
257
+ error: {
258
+ code: string;
259
+ message: string;
260
+ };
261
+ }
262
+ interface RelayPing {
263
+ type: 'relay:ping';
264
+ ts: number;
265
+ }
266
+ interface RelayPong {
267
+ type: 'relay:pong';
268
+ ts: number;
269
+ }
270
+ type RelayMessage = RelayHello | RelayRequest | RelayResponseMeta | RelayResponseChunk | RelayResponseDone | RelayResponseError | RelayPing | RelayPong;
271
+ declare function parseRelayMessage(data: unknown): RelayMessage | null;
272
+ declare function sendRelayMessage(ws: WebSocketLike, msg: RelayMessage): void;
273
+
274
+ interface PasswordStrength {
275
+ score: 0 | 1 | 2 | 3 | 4;
276
+ label: 'Too weak' | 'Weak' | 'Fair' | 'Strong' | 'Very strong';
277
+ feedback: string[];
278
+ }
279
+ declare function checkPasswordStrength(password: string): PasswordStrength;
280
+ declare const MIN_PASSWORD_LENGTH = 12;
281
+
282
+ /**
283
+ * Validate that a proxy request URL targets the registered provider's base URL.
284
+ * Prevents API key exfiltration by rejecting requests to arbitrary domains.
285
+ */
286
+ declare function validateProxyUrl(providerId: string, url: string): boolean;
287
+ /**
288
+ * Build the real auth headers for a provider API request.
289
+ * Strips any fake session-key headers and injects the real API key.
290
+ */
291
+ declare function buildHeaders(providerId: string, requestHeaders: Record<string, string>, apiKey: string, authMethod?: string): Record<string, string>;
292
+ /**
293
+ * Parse the model name from a request body (JSON).
294
+ */
295
+ declare function parseModel(body?: string): string | undefined;
296
+ /**
297
+ * Parse token usage from a provider API response body.
298
+ * Handles both regular JSON responses and SSE streaming responses.
299
+ */
300
+ declare function parseUsage(providerId: string, body: string): {
301
+ inputTokens: number;
302
+ outputTokens: number;
303
+ } | undefined;
304
+ /**
305
+ * Extract token usage from a parsed provider response object.
306
+ */
307
+ declare function extractUsageFromParsed(providerId: string, parsed: Record<string, unknown>): {
308
+ inputTokens: number;
309
+ outputTokens: number;
310
+ } | undefined;
311
+ /**
312
+ * Check whether a request is allowed given token allowances and usage history.
313
+ * Pure computation — no storage access.
314
+ */
315
+ declare function computeAllowanceCheck(allowance: TokenAllowance | undefined, entries: Pick<RequestLogEntry, 'providerId' | 'inputTokens' | 'outputTokens'>[], providerId: string): {
316
+ allowed: boolean;
317
+ reason?: string;
318
+ };
319
+
320
+ export { type ApiKeyCredential, type AuthMethod, BYOKY_MESSAGE_PREFIX, BYOKY_PROVIDER_KEY, ByokyError, ByokyErrorCode, type ByokyMessage, type ConnectRequest, type ConnectResponse, type Credential, type CredentialBase, type CredentialMeta, MIN_PASSWORD_LENGTH, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PasswordStrength, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RelayHello, type RelayMessage, type RelayPing, type RelayPong, type RelayRequest, type RelayResponseChunk, type RelayResponseDone, type RelayResponseError, type RelayResponseMeta, type RequestLogEntry, type Session, type SessionProvider, type SessionUsage, type TokenAllowance, type TrustedSite, WS_READY_STATE, type WebSocketLike, buildHeaders, checkPasswordStrength, computeAllowanceCheck, createConnectRequest, createConnectResponse, createErrorMessage, createMessage, decrypt, deriveKey, encrypt, extractUsageFromParsed, getProvider, getProviderIds, hashPassword, isByokyMessage, maskKey, parseModel, parseRelayMessage, parseUsage, sendRelayMessage, validateProxyUrl, verifyPassword };