@byoky/core 0.3.0 → 0.4.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/LICENSE +21 -0
- package/dist/index.cjs +203 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -5
- package/dist/index.d.ts +111 -5
- package/dist/index.js +192 -14
- package/dist/index.js.map +1 -1
- package/package.json +20 -9
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,9 @@ interface SessionProvider {
|
|
|
56
56
|
credentialId: string;
|
|
57
57
|
available: boolean;
|
|
58
58
|
authMethod: AuthMethod;
|
|
59
|
+
giftId?: string;
|
|
60
|
+
giftRelayUrl?: string;
|
|
61
|
+
giftAuthToken?: string;
|
|
59
62
|
}
|
|
60
63
|
interface ConnectRequest {
|
|
61
64
|
providers?: ProviderRequirement[];
|
|
@@ -155,6 +158,7 @@ interface PendingApproval {
|
|
|
155
158
|
interface TrustedSite {
|
|
156
159
|
origin: string;
|
|
157
160
|
trustedAt: number;
|
|
161
|
+
allowedProviders?: string[];
|
|
158
162
|
}
|
|
159
163
|
interface TokenAllowance {
|
|
160
164
|
origin: string;
|
|
@@ -267,7 +271,17 @@ interface RelayPong {
|
|
|
267
271
|
type: 'relay:pong';
|
|
268
272
|
ts: number;
|
|
269
273
|
}
|
|
270
|
-
|
|
274
|
+
interface RelayPairHello {
|
|
275
|
+
type: 'relay:pair:hello';
|
|
276
|
+
providers: Record<string, {
|
|
277
|
+
available: boolean;
|
|
278
|
+
authMethod: AuthMethod;
|
|
279
|
+
}>;
|
|
280
|
+
}
|
|
281
|
+
interface RelayPairAck {
|
|
282
|
+
type: 'relay:pair:ack';
|
|
283
|
+
}
|
|
284
|
+
type RelayMessage = RelayHello | RelayRequest | RelayResponseMeta | RelayResponseChunk | RelayResponseDone | RelayResponseError | RelayPing | RelayPong | RelayPairHello | RelayPairAck;
|
|
271
285
|
declare function parseRelayMessage(data: unknown): RelayMessage | null;
|
|
272
286
|
declare function sendRelayMessage(ws: WebSocketLike, msg: RelayMessage): void;
|
|
273
287
|
|
|
@@ -289,9 +303,6 @@ declare function validateProxyUrl(providerId: string, url: string): boolean;
|
|
|
289
303
|
* Strips any fake session-key headers and injects the real API key.
|
|
290
304
|
*/
|
|
291
305
|
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
306
|
declare function parseModel(body?: string): string | undefined;
|
|
296
307
|
/**
|
|
297
308
|
* Parse token usage from a provider API response body.
|
|
@@ -317,4 +328,99 @@ declare function computeAllowanceCheck(allowance: TokenAllowance | undefined, en
|
|
|
317
328
|
reason?: string;
|
|
318
329
|
};
|
|
319
330
|
|
|
320
|
-
|
|
331
|
+
interface Gift {
|
|
332
|
+
id: string;
|
|
333
|
+
credentialId: string;
|
|
334
|
+
providerId: string;
|
|
335
|
+
label: string;
|
|
336
|
+
authToken: string;
|
|
337
|
+
maxTokens: number;
|
|
338
|
+
usedTokens: number;
|
|
339
|
+
expiresAt: number;
|
|
340
|
+
createdAt: number;
|
|
341
|
+
active: boolean;
|
|
342
|
+
relayUrl: string;
|
|
343
|
+
}
|
|
344
|
+
interface GiftLink {
|
|
345
|
+
v: 1;
|
|
346
|
+
id: string;
|
|
347
|
+
p: string;
|
|
348
|
+
n: string;
|
|
349
|
+
s: string;
|
|
350
|
+
t: string;
|
|
351
|
+
m: number;
|
|
352
|
+
e: number;
|
|
353
|
+
r: string;
|
|
354
|
+
}
|
|
355
|
+
interface GiftedCredential {
|
|
356
|
+
id: string;
|
|
357
|
+
giftId: string;
|
|
358
|
+
providerId: string;
|
|
359
|
+
providerName: string;
|
|
360
|
+
senderLabel: string;
|
|
361
|
+
authToken: string;
|
|
362
|
+
maxTokens: number;
|
|
363
|
+
usedTokens: number;
|
|
364
|
+
expiresAt: number;
|
|
365
|
+
relayUrl: string;
|
|
366
|
+
createdAt: number;
|
|
367
|
+
}
|
|
368
|
+
interface RelayAuth {
|
|
369
|
+
type: 'relay:auth';
|
|
370
|
+
roomId: string;
|
|
371
|
+
authToken: string;
|
|
372
|
+
role: 'sender' | 'recipient';
|
|
373
|
+
}
|
|
374
|
+
interface RelayAuthResult {
|
|
375
|
+
type: 'relay:auth:result';
|
|
376
|
+
success: boolean;
|
|
377
|
+
error?: string;
|
|
378
|
+
peerOnline?: boolean;
|
|
379
|
+
}
|
|
380
|
+
interface RelayPeerStatus {
|
|
381
|
+
type: 'relay:peer:status';
|
|
382
|
+
online: boolean;
|
|
383
|
+
}
|
|
384
|
+
interface RelayUsageUpdate {
|
|
385
|
+
type: 'relay:usage';
|
|
386
|
+
roomId: string;
|
|
387
|
+
usedTokens: number;
|
|
388
|
+
}
|
|
389
|
+
type RelayProtocolMessage = RelayAuth | RelayAuthResult | RelayPeerStatus | RelayUsageUpdate;
|
|
390
|
+
declare function encodeGiftLink(link: GiftLink): string;
|
|
391
|
+
declare function decodeGiftLink(encoded: string): GiftLink | null;
|
|
392
|
+
declare function giftLinkToUrl(encoded: string): string;
|
|
393
|
+
declare function validateGiftLink(link: GiftLink): {
|
|
394
|
+
valid: boolean;
|
|
395
|
+
reason?: string;
|
|
396
|
+
};
|
|
397
|
+
declare function isGiftExpired(gift: {
|
|
398
|
+
expiresAt: number;
|
|
399
|
+
}): boolean;
|
|
400
|
+
declare function isGiftBudgetExhausted(gift: {
|
|
401
|
+
usedTokens: number;
|
|
402
|
+
maxTokens: number;
|
|
403
|
+
}): boolean;
|
|
404
|
+
declare function giftBudgetRemaining(gift: {
|
|
405
|
+
usedTokens: number;
|
|
406
|
+
maxTokens: number;
|
|
407
|
+
}): number;
|
|
408
|
+
declare function giftBudgetPercent(gift: {
|
|
409
|
+
usedTokens: number;
|
|
410
|
+
maxTokens: number;
|
|
411
|
+
}): number;
|
|
412
|
+
declare function createGiftLink(gift: Gift): {
|
|
413
|
+
encoded: string;
|
|
414
|
+
link: GiftLink;
|
|
415
|
+
};
|
|
416
|
+
interface PairPayload {
|
|
417
|
+
v: 1;
|
|
418
|
+
r: string;
|
|
419
|
+
id: string;
|
|
420
|
+
t: string;
|
|
421
|
+
o: string;
|
|
422
|
+
}
|
|
423
|
+
declare function encodePairPayload(payload: PairPayload): string;
|
|
424
|
+
declare function decodePairPayload(encoded: string): PairPayload | null;
|
|
425
|
+
|
|
426
|
+
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 Gift, type GiftLink, type GiftedCredential, MIN_PASSWORD_LENGTH, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PairPayload, type PasswordStrength, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RelayAuth, type RelayAuthResult, type RelayHello, type RelayMessage, type RelayPairAck, type RelayPairHello, type RelayPeerStatus, type RelayPing, type RelayPong, type RelayProtocolMessage, type RelayRequest, type RelayResponseChunk, type RelayResponseDone, type RelayResponseError, type RelayResponseMeta, type RelayUsageUpdate, type RequestLogEntry, type Session, type SessionProvider, type SessionUsage, type TokenAllowance, type TrustedSite, WS_READY_STATE, type WebSocketLike, buildHeaders, checkPasswordStrength, computeAllowanceCheck, createConnectRequest, createConnectResponse, createErrorMessage, createGiftLink, createMessage, decodeGiftLink, decodePairPayload, decrypt, deriveKey, encodeGiftLink, encodePairPayload, encrypt, extractUsageFromParsed, getProvider, getProviderIds, giftBudgetPercent, giftBudgetRemaining, giftLinkToUrl, hashPassword, isByokyMessage, isGiftBudgetExhausted, isGiftExpired, maskKey, parseModel, parseRelayMessage, parseUsage, sendRelayMessage, validateGiftLink, validateProxyUrl, verifyPassword };
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,9 @@ interface SessionProvider {
|
|
|
56
56
|
credentialId: string;
|
|
57
57
|
available: boolean;
|
|
58
58
|
authMethod: AuthMethod;
|
|
59
|
+
giftId?: string;
|
|
60
|
+
giftRelayUrl?: string;
|
|
61
|
+
giftAuthToken?: string;
|
|
59
62
|
}
|
|
60
63
|
interface ConnectRequest {
|
|
61
64
|
providers?: ProviderRequirement[];
|
|
@@ -155,6 +158,7 @@ interface PendingApproval {
|
|
|
155
158
|
interface TrustedSite {
|
|
156
159
|
origin: string;
|
|
157
160
|
trustedAt: number;
|
|
161
|
+
allowedProviders?: string[];
|
|
158
162
|
}
|
|
159
163
|
interface TokenAllowance {
|
|
160
164
|
origin: string;
|
|
@@ -267,7 +271,17 @@ interface RelayPong {
|
|
|
267
271
|
type: 'relay:pong';
|
|
268
272
|
ts: number;
|
|
269
273
|
}
|
|
270
|
-
|
|
274
|
+
interface RelayPairHello {
|
|
275
|
+
type: 'relay:pair:hello';
|
|
276
|
+
providers: Record<string, {
|
|
277
|
+
available: boolean;
|
|
278
|
+
authMethod: AuthMethod;
|
|
279
|
+
}>;
|
|
280
|
+
}
|
|
281
|
+
interface RelayPairAck {
|
|
282
|
+
type: 'relay:pair:ack';
|
|
283
|
+
}
|
|
284
|
+
type RelayMessage = RelayHello | RelayRequest | RelayResponseMeta | RelayResponseChunk | RelayResponseDone | RelayResponseError | RelayPing | RelayPong | RelayPairHello | RelayPairAck;
|
|
271
285
|
declare function parseRelayMessage(data: unknown): RelayMessage | null;
|
|
272
286
|
declare function sendRelayMessage(ws: WebSocketLike, msg: RelayMessage): void;
|
|
273
287
|
|
|
@@ -289,9 +303,6 @@ declare function validateProxyUrl(providerId: string, url: string): boolean;
|
|
|
289
303
|
* Strips any fake session-key headers and injects the real API key.
|
|
290
304
|
*/
|
|
291
305
|
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
306
|
declare function parseModel(body?: string): string | undefined;
|
|
296
307
|
/**
|
|
297
308
|
* Parse token usage from a provider API response body.
|
|
@@ -317,4 +328,99 @@ declare function computeAllowanceCheck(allowance: TokenAllowance | undefined, en
|
|
|
317
328
|
reason?: string;
|
|
318
329
|
};
|
|
319
330
|
|
|
320
|
-
|
|
331
|
+
interface Gift {
|
|
332
|
+
id: string;
|
|
333
|
+
credentialId: string;
|
|
334
|
+
providerId: string;
|
|
335
|
+
label: string;
|
|
336
|
+
authToken: string;
|
|
337
|
+
maxTokens: number;
|
|
338
|
+
usedTokens: number;
|
|
339
|
+
expiresAt: number;
|
|
340
|
+
createdAt: number;
|
|
341
|
+
active: boolean;
|
|
342
|
+
relayUrl: string;
|
|
343
|
+
}
|
|
344
|
+
interface GiftLink {
|
|
345
|
+
v: 1;
|
|
346
|
+
id: string;
|
|
347
|
+
p: string;
|
|
348
|
+
n: string;
|
|
349
|
+
s: string;
|
|
350
|
+
t: string;
|
|
351
|
+
m: number;
|
|
352
|
+
e: number;
|
|
353
|
+
r: string;
|
|
354
|
+
}
|
|
355
|
+
interface GiftedCredential {
|
|
356
|
+
id: string;
|
|
357
|
+
giftId: string;
|
|
358
|
+
providerId: string;
|
|
359
|
+
providerName: string;
|
|
360
|
+
senderLabel: string;
|
|
361
|
+
authToken: string;
|
|
362
|
+
maxTokens: number;
|
|
363
|
+
usedTokens: number;
|
|
364
|
+
expiresAt: number;
|
|
365
|
+
relayUrl: string;
|
|
366
|
+
createdAt: number;
|
|
367
|
+
}
|
|
368
|
+
interface RelayAuth {
|
|
369
|
+
type: 'relay:auth';
|
|
370
|
+
roomId: string;
|
|
371
|
+
authToken: string;
|
|
372
|
+
role: 'sender' | 'recipient';
|
|
373
|
+
}
|
|
374
|
+
interface RelayAuthResult {
|
|
375
|
+
type: 'relay:auth:result';
|
|
376
|
+
success: boolean;
|
|
377
|
+
error?: string;
|
|
378
|
+
peerOnline?: boolean;
|
|
379
|
+
}
|
|
380
|
+
interface RelayPeerStatus {
|
|
381
|
+
type: 'relay:peer:status';
|
|
382
|
+
online: boolean;
|
|
383
|
+
}
|
|
384
|
+
interface RelayUsageUpdate {
|
|
385
|
+
type: 'relay:usage';
|
|
386
|
+
roomId: string;
|
|
387
|
+
usedTokens: number;
|
|
388
|
+
}
|
|
389
|
+
type RelayProtocolMessage = RelayAuth | RelayAuthResult | RelayPeerStatus | RelayUsageUpdate;
|
|
390
|
+
declare function encodeGiftLink(link: GiftLink): string;
|
|
391
|
+
declare function decodeGiftLink(encoded: string): GiftLink | null;
|
|
392
|
+
declare function giftLinkToUrl(encoded: string): string;
|
|
393
|
+
declare function validateGiftLink(link: GiftLink): {
|
|
394
|
+
valid: boolean;
|
|
395
|
+
reason?: string;
|
|
396
|
+
};
|
|
397
|
+
declare function isGiftExpired(gift: {
|
|
398
|
+
expiresAt: number;
|
|
399
|
+
}): boolean;
|
|
400
|
+
declare function isGiftBudgetExhausted(gift: {
|
|
401
|
+
usedTokens: number;
|
|
402
|
+
maxTokens: number;
|
|
403
|
+
}): boolean;
|
|
404
|
+
declare function giftBudgetRemaining(gift: {
|
|
405
|
+
usedTokens: number;
|
|
406
|
+
maxTokens: number;
|
|
407
|
+
}): number;
|
|
408
|
+
declare function giftBudgetPercent(gift: {
|
|
409
|
+
usedTokens: number;
|
|
410
|
+
maxTokens: number;
|
|
411
|
+
}): number;
|
|
412
|
+
declare function createGiftLink(gift: Gift): {
|
|
413
|
+
encoded: string;
|
|
414
|
+
link: GiftLink;
|
|
415
|
+
};
|
|
416
|
+
interface PairPayload {
|
|
417
|
+
v: 1;
|
|
418
|
+
r: string;
|
|
419
|
+
id: string;
|
|
420
|
+
t: string;
|
|
421
|
+
o: string;
|
|
422
|
+
}
|
|
423
|
+
declare function encodePairPayload(payload: PairPayload): string;
|
|
424
|
+
declare function decodePairPayload(encoded: string): PairPayload | null;
|
|
425
|
+
|
|
426
|
+
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 Gift, type GiftLink, type GiftedCredential, MIN_PASSWORD_LENGTH, type MessageType, type OAuthConfig, type OAuthCredential, PROVIDERS, type PairPayload, type PasswordStrength, type PendingApproval, type ProviderConfig, type ProviderId, type ProviderRequirement, type ProxyRequest, type ProxyResponseChunk, type ProxyResponseError, type ProxyResponseMeta, type RelayAuth, type RelayAuthResult, type RelayHello, type RelayMessage, type RelayPairAck, type RelayPairHello, type RelayPeerStatus, type RelayPing, type RelayPong, type RelayProtocolMessage, type RelayRequest, type RelayResponseChunk, type RelayResponseDone, type RelayResponseError, type RelayResponseMeta, type RelayUsageUpdate, type RequestLogEntry, type Session, type SessionProvider, type SessionUsage, type TokenAllowance, type TrustedSite, WS_READY_STATE, type WebSocketLike, buildHeaders, checkPasswordStrength, computeAllowanceCheck, createConnectRequest, createConnectResponse, createErrorMessage, createGiftLink, createMessage, decodeGiftLink, decodePairPayload, decrypt, deriveKey, encodeGiftLink, encodePairPayload, encrypt, extractUsageFromParsed, getProvider, getProviderIds, giftBudgetPercent, giftBudgetRemaining, giftLinkToUrl, hashPassword, isByokyMessage, isGiftBudgetExhausted, isGiftExpired, maskKey, parseModel, parseRelayMessage, parseUsage, sendRelayMessage, validateGiftLink, validateProxyUrl, verifyPassword };
|
package/dist/index.js
CHANGED
|
@@ -325,8 +325,10 @@ var WS_READY_STATE = {
|
|
|
325
325
|
CLOSING: 2,
|
|
326
326
|
CLOSED: 3
|
|
327
327
|
};
|
|
328
|
+
var MAX_RELAY_MESSAGE_SIZE = 1048576;
|
|
328
329
|
function parseRelayMessage(data) {
|
|
329
330
|
try {
|
|
331
|
+
if (typeof data === "string" && data.length > MAX_RELAY_MESSAGE_SIZE) return null;
|
|
330
332
|
const raw = typeof data === "string" ? JSON.parse(data) : data;
|
|
331
333
|
if (!raw || typeof raw !== "object" || typeof raw.type !== "string" || !raw.type.startsWith("relay:")) {
|
|
332
334
|
return null;
|
|
@@ -345,13 +347,21 @@ function parseRelayMessage(data) {
|
|
|
345
347
|
if (typeof raw.requestId !== "string" || typeof raw.chunk !== "string") return null;
|
|
346
348
|
break;
|
|
347
349
|
case "relay:response:done":
|
|
350
|
+
if (typeof raw.requestId !== "string") return null;
|
|
351
|
+
break;
|
|
348
352
|
case "relay:response:error":
|
|
349
353
|
if (typeof raw.requestId !== "string") return null;
|
|
354
|
+
if (raw.error && (typeof raw.error !== "object" || typeof raw.error.code !== "string" || typeof raw.error.message !== "string")) return null;
|
|
350
355
|
break;
|
|
351
356
|
case "relay:ping":
|
|
352
357
|
case "relay:pong":
|
|
353
358
|
if (typeof raw.ts !== "number") return null;
|
|
354
359
|
break;
|
|
360
|
+
case "relay:pair:hello":
|
|
361
|
+
if (!raw.providers || typeof raw.providers !== "object") return null;
|
|
362
|
+
break;
|
|
363
|
+
case "relay:pair:ack":
|
|
364
|
+
break;
|
|
355
365
|
default:
|
|
356
366
|
return null;
|
|
357
367
|
}
|
|
@@ -387,16 +397,59 @@ var COMMON_PASSWORDS = /* @__PURE__ */ new Set([
|
|
|
387
397
|
"shadow123",
|
|
388
398
|
"michael1",
|
|
389
399
|
"jordan123",
|
|
390
|
-
"superman1"
|
|
400
|
+
"superman1",
|
|
401
|
+
"password123",
|
|
402
|
+
"admin12345",
|
|
403
|
+
"letmein123",
|
|
404
|
+
"p@ssw0rd",
|
|
405
|
+
"p@ssw0rd1",
|
|
406
|
+
"qwerty1234",
|
|
407
|
+
"changeme12",
|
|
408
|
+
"welcome123",
|
|
409
|
+
"1234567890",
|
|
410
|
+
"baseball1",
|
|
411
|
+
"starwars12",
|
|
412
|
+
"whatever1",
|
|
413
|
+
"passw0rd1",
|
|
414
|
+
"mustang12",
|
|
415
|
+
"access1234",
|
|
416
|
+
"charlie123",
|
|
417
|
+
"donald1234",
|
|
418
|
+
"maggie1234",
|
|
419
|
+
"master1234",
|
|
420
|
+
"michael123",
|
|
421
|
+
"jennifer1",
|
|
422
|
+
"hunter1234",
|
|
423
|
+
"thomas1234",
|
|
424
|
+
"corvette12",
|
|
425
|
+
"robert1234",
|
|
426
|
+
"summer1234",
|
|
427
|
+
"george1234",
|
|
428
|
+
"harley1234",
|
|
429
|
+
"cheese1234",
|
|
430
|
+
"computer1",
|
|
431
|
+
"internet1",
|
|
432
|
+
"secret1234",
|
|
433
|
+
"diamond1",
|
|
434
|
+
"chicken123",
|
|
435
|
+
"pepper1234",
|
|
436
|
+
"jessica123",
|
|
437
|
+
"hannah1234",
|
|
438
|
+
"ginger1234",
|
|
439
|
+
"joshua1234",
|
|
440
|
+
"abcdefgh1",
|
|
441
|
+
"qwertyuiop",
|
|
442
|
+
"asdfghjkl1",
|
|
443
|
+
"zxcvbnm123",
|
|
444
|
+
"1q2w3e4r5t",
|
|
445
|
+
"passpass1"
|
|
391
446
|
]);
|
|
392
447
|
function checkPasswordStrength(password) {
|
|
393
448
|
const feedback = [];
|
|
394
449
|
let score = 0;
|
|
395
|
-
if (password.length <
|
|
450
|
+
if (password.length < MIN_PASSWORD_LENGTH) {
|
|
396
451
|
feedback.push("Use at least 12 characters");
|
|
397
|
-
|
|
398
|
-
return { score: 0, label: "Too weak", feedback };
|
|
399
|
-
}
|
|
452
|
+
return { score: 0, label: "Too weak", feedback };
|
|
400
453
|
} else {
|
|
401
454
|
score++;
|
|
402
455
|
if (password.length >= 16) score++;
|
|
@@ -462,12 +515,23 @@ function buildHeaders(providerId, requestHeaders, apiKey, authMethod = "api_key"
|
|
|
462
515
|
delete headers["authorization"];
|
|
463
516
|
delete headers["x-api-key"];
|
|
464
517
|
delete headers["api-key"];
|
|
518
|
+
delete headers["origin"];
|
|
519
|
+
delete headers["referer"];
|
|
520
|
+
for (const key of Object.keys(headers)) {
|
|
521
|
+
if (key.startsWith("x-stainless-")) delete headers[key];
|
|
522
|
+
}
|
|
523
|
+
delete headers["sec-fetch-mode"];
|
|
524
|
+
delete headers["accept-language"];
|
|
525
|
+
delete headers["accept-encoding"];
|
|
526
|
+
delete headers["content-length"];
|
|
465
527
|
if (providerId === "anthropic") {
|
|
466
528
|
if (authMethod === "oauth") {
|
|
467
529
|
headers["authorization"] = `Bearer ${apiKey}`;
|
|
468
|
-
headers["user-agent"] = "claude-cli/2.1.
|
|
530
|
+
headers["user-agent"] = "claude-cli/2.1.76";
|
|
469
531
|
headers["x-app"] = "cli";
|
|
470
|
-
headers["
|
|
532
|
+
headers["accept"] = "application/json";
|
|
533
|
+
headers["anthropic-beta"] = "claude-code-20250219,oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14,interleaved-thinking-2025-05-14";
|
|
534
|
+
headers["anthropic-dangerous-direct-browser-access"] = "true";
|
|
471
535
|
} else {
|
|
472
536
|
headers["x-api-key"] = apiKey;
|
|
473
537
|
}
|
|
@@ -479,8 +543,9 @@ function buildHeaders(providerId, requestHeaders, apiKey, authMethod = "api_key"
|
|
|
479
543
|
}
|
|
480
544
|
return headers;
|
|
481
545
|
}
|
|
546
|
+
var MAX_BODY_PARSE_SIZE = 10485760;
|
|
482
547
|
function parseModel(body) {
|
|
483
|
-
if (!body) return void 0;
|
|
548
|
+
if (!body || body.length > MAX_BODY_PARSE_SIZE) return void 0;
|
|
484
549
|
try {
|
|
485
550
|
const parsed = JSON.parse(body);
|
|
486
551
|
return parsed.model ?? void 0;
|
|
@@ -510,25 +575,28 @@ function parseUsage(providerId, body) {
|
|
|
510
575
|
return void 0;
|
|
511
576
|
}
|
|
512
577
|
}
|
|
578
|
+
function sanitizeTokenCounts(input, output) {
|
|
579
|
+
const i = Math.max(0, Math.floor(input));
|
|
580
|
+
const o = Math.max(0, Math.floor(output));
|
|
581
|
+
if (!Number.isFinite(i) || !Number.isFinite(o)) return void 0;
|
|
582
|
+
return { inputTokens: i, outputTokens: o };
|
|
583
|
+
}
|
|
513
584
|
function extractUsageFromParsed(providerId, parsed) {
|
|
514
585
|
if (providerId === "anthropic") {
|
|
515
586
|
const usage2 = parsed.usage;
|
|
516
587
|
if (usage2?.input_tokens != null && usage2?.output_tokens != null) {
|
|
517
|
-
return
|
|
588
|
+
return sanitizeTokenCounts(usage2.input_tokens, usage2.output_tokens);
|
|
518
589
|
}
|
|
519
590
|
}
|
|
520
591
|
if (providerId === "gemini") {
|
|
521
592
|
const meta = parsed.usageMetadata;
|
|
522
593
|
if (meta?.promptTokenCount != null) {
|
|
523
|
-
return
|
|
524
|
-
inputTokens: meta.promptTokenCount,
|
|
525
|
-
outputTokens: meta.candidatesTokenCount ?? 0
|
|
526
|
-
};
|
|
594
|
+
return sanitizeTokenCounts(meta.promptTokenCount, meta.candidatesTokenCount ?? 0);
|
|
527
595
|
}
|
|
528
596
|
}
|
|
529
597
|
const usage = parsed.usage;
|
|
530
598
|
if (usage?.prompt_tokens != null && usage?.completion_tokens != null) {
|
|
531
|
-
return
|
|
599
|
+
return sanitizeTokenCounts(usage.prompt_tokens, usage.completion_tokens);
|
|
532
600
|
}
|
|
533
601
|
return void 0;
|
|
534
602
|
}
|
|
@@ -550,6 +618,105 @@ function computeAllowanceCheck(allowance, entries, providerId) {
|
|
|
550
618
|
}
|
|
551
619
|
return { allowed: true };
|
|
552
620
|
}
|
|
621
|
+
|
|
622
|
+
// src/gift.ts
|
|
623
|
+
function encodeGiftLink(link) {
|
|
624
|
+
const json = JSON.stringify(link);
|
|
625
|
+
const bytes = new TextEncoder().encode(json);
|
|
626
|
+
return base64UrlEncode(bytes);
|
|
627
|
+
}
|
|
628
|
+
var MAX_GIFT_LINK_SIZE = 8192;
|
|
629
|
+
function decodeGiftLink(encoded) {
|
|
630
|
+
try {
|
|
631
|
+
if (encoded.length > MAX_GIFT_LINK_SIZE) return null;
|
|
632
|
+
const clean = encoded.replace(/^byoky:\/\/gift\//, "");
|
|
633
|
+
const bytes = base64UrlDecode(clean);
|
|
634
|
+
const json = new TextDecoder().decode(bytes);
|
|
635
|
+
const parsed = JSON.parse(json);
|
|
636
|
+
if (parsed.v !== 1) return null;
|
|
637
|
+
return parsed;
|
|
638
|
+
} catch {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
function giftLinkToUrl(encoded) {
|
|
643
|
+
return `byoky://gift/${encoded}`;
|
|
644
|
+
}
|
|
645
|
+
function validateGiftLink(link) {
|
|
646
|
+
if (link.v !== 1) return { valid: false, reason: "Unsupported gift version" };
|
|
647
|
+
if (!link.id || typeof link.id !== "string") return { valid: false, reason: "Missing gift ID" };
|
|
648
|
+
if (!link.p || typeof link.p !== "string") return { valid: false, reason: "Missing provider" };
|
|
649
|
+
if (!link.t || typeof link.t !== "string") return { valid: false, reason: "Missing auth token" };
|
|
650
|
+
if (!link.r || typeof link.r !== "string") return { valid: false, reason: "Missing relay URL" };
|
|
651
|
+
if (typeof link.m !== "number" || link.m <= 0) return { valid: false, reason: "Invalid token budget" };
|
|
652
|
+
if (typeof link.e !== "number" || link.e <= Date.now()) return { valid: false, reason: "Gift has expired" };
|
|
653
|
+
try {
|
|
654
|
+
const url = new URL(link.r);
|
|
655
|
+
if (url.protocol !== "ws:" && url.protocol !== "wss:") {
|
|
656
|
+
return { valid: false, reason: "Relay URL must use ws:// or wss://" };
|
|
657
|
+
}
|
|
658
|
+
} catch {
|
|
659
|
+
return { valid: false, reason: "Invalid relay URL" };
|
|
660
|
+
}
|
|
661
|
+
return { valid: true };
|
|
662
|
+
}
|
|
663
|
+
function isGiftExpired(gift) {
|
|
664
|
+
return gift.expiresAt <= Date.now();
|
|
665
|
+
}
|
|
666
|
+
function isGiftBudgetExhausted(gift) {
|
|
667
|
+
return gift.usedTokens >= gift.maxTokens;
|
|
668
|
+
}
|
|
669
|
+
function giftBudgetRemaining(gift) {
|
|
670
|
+
return Math.max(0, gift.maxTokens - gift.usedTokens);
|
|
671
|
+
}
|
|
672
|
+
function giftBudgetPercent(gift) {
|
|
673
|
+
if (gift.maxTokens === 0) return 100;
|
|
674
|
+
return Math.min(100, Math.round(gift.usedTokens / gift.maxTokens * 100));
|
|
675
|
+
}
|
|
676
|
+
function createGiftLink(gift) {
|
|
677
|
+
const provider = PROVIDERS[gift.providerId];
|
|
678
|
+
const link = {
|
|
679
|
+
v: 1,
|
|
680
|
+
id: gift.id,
|
|
681
|
+
p: gift.providerId,
|
|
682
|
+
n: provider?.name ?? gift.providerId,
|
|
683
|
+
s: gift.label,
|
|
684
|
+
t: gift.authToken,
|
|
685
|
+
m: gift.maxTokens,
|
|
686
|
+
e: gift.expiresAt,
|
|
687
|
+
r: gift.relayUrl
|
|
688
|
+
};
|
|
689
|
+
return { encoded: encodeGiftLink(link), link };
|
|
690
|
+
}
|
|
691
|
+
function encodePairPayload(payload) {
|
|
692
|
+
const json = JSON.stringify(payload);
|
|
693
|
+
const bytes = new TextEncoder().encode(json);
|
|
694
|
+
return base64UrlEncode(bytes);
|
|
695
|
+
}
|
|
696
|
+
function decodePairPayload(encoded) {
|
|
697
|
+
try {
|
|
698
|
+
if (encoded.length > 2048) return null;
|
|
699
|
+
const bytes = base64UrlDecode(encoded);
|
|
700
|
+
const json = new TextDecoder().decode(bytes);
|
|
701
|
+
const parsed = JSON.parse(json);
|
|
702
|
+
if (parsed.v !== 1) return null;
|
|
703
|
+
return parsed;
|
|
704
|
+
} catch {
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
function base64UrlEncode(bytes) {
|
|
709
|
+
let binary = "";
|
|
710
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
711
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
712
|
+
}
|
|
713
|
+
function base64UrlDecode(str) {
|
|
714
|
+
const padded = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
715
|
+
const binary = atob(padded);
|
|
716
|
+
const bytes = new Uint8Array(binary.length);
|
|
717
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
718
|
+
return bytes;
|
|
719
|
+
}
|
|
553
720
|
export {
|
|
554
721
|
BYOKY_MESSAGE_PREFIX,
|
|
555
722
|
BYOKY_PROVIDER_KEY,
|
|
@@ -564,20 +731,31 @@ export {
|
|
|
564
731
|
createConnectRequest,
|
|
565
732
|
createConnectResponse,
|
|
566
733
|
createErrorMessage,
|
|
734
|
+
createGiftLink,
|
|
567
735
|
createMessage,
|
|
736
|
+
decodeGiftLink,
|
|
737
|
+
decodePairPayload,
|
|
568
738
|
decrypt,
|
|
569
739
|
deriveKey,
|
|
740
|
+
encodeGiftLink,
|
|
741
|
+
encodePairPayload,
|
|
570
742
|
encrypt,
|
|
571
743
|
extractUsageFromParsed,
|
|
572
744
|
getProvider,
|
|
573
745
|
getProviderIds,
|
|
746
|
+
giftBudgetPercent,
|
|
747
|
+
giftBudgetRemaining,
|
|
748
|
+
giftLinkToUrl,
|
|
574
749
|
hashPassword,
|
|
575
750
|
isByokyMessage,
|
|
751
|
+
isGiftBudgetExhausted,
|
|
752
|
+
isGiftExpired,
|
|
576
753
|
maskKey,
|
|
577
754
|
parseModel,
|
|
578
755
|
parseRelayMessage,
|
|
579
756
|
parseUsage,
|
|
580
757
|
sendRelayMessage,
|
|
758
|
+
validateGiftLink,
|
|
581
759
|
validateProxyUrl,
|
|
582
760
|
verifyPassword
|
|
583
761
|
};
|