@jeffusion/bungee-core 5.20.0 → 5.21.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/config-worker/private-transport.d.ts +2 -0
- package/dist/data-admission/errors.d.ts +6 -1
- package/dist/gateway/contracts.d.ts +15 -4
- package/dist/gateway/forward-plugin.d.ts +2 -0
- package/dist/gateway/plugin.js +12 -2
- package/dist/gateway/request-plugin.d.ts +6 -0
- package/dist/gateway/responses-websocket-session.d.ts +18 -0
- package/dist/gateway/runtime.d.ts +1 -0
- package/dist/gateway/websocket-contracts.d.ts +1 -0
- package/dist/hooks/plugin-hooks.d.ts +2 -3
- package/dist/logger/access-log-writer.d.ts +2 -2
- package/dist/main.js +1199 -176
- package/dist/plugins/ai-transformer/index.js +1 -1
- package/dist/plugins/ai-transformer/index.js.map +4 -4
- package/dist/plugins/codex-router/control.js +6 -2
- package/dist/plugins/codex-router/control.js.map +4 -4
- package/dist/plugins/codex-router/index.js +498 -165
- package/dist/plugins/codex-router/index.js.map +13 -11
- package/dist/plugins/codex-router/manifest.json +124 -8
- package/dist/plugins/key-access/index.js +12 -2
- package/dist/plugins/key-access/index.js.map +3 -3
- package/dist/plugins/key-access/ingress.js +12 -2
- package/dist/plugins/key-access/ingress.js.map +3 -3
- package/dist/plugins/openai-messages-to-chat/index.js +6 -4
- package/dist/plugins/openai-messages-to-chat/index.js.map +4 -4
- package/dist/plugins/token-metering/index.js +1 -1
- package/dist/plugins/token-metering/index.js.map +4 -4
- package/dist/plugins/token-stats/manifest.json +16 -6
- package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +13 -61
- package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +18 -74
- package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +3 -2
- package/dist/plugins/token-stats/ui/model-search.ts +2 -45
- package/dist/plugins/token-stats/ui/pricing-catalog.ts +2 -1
- package/dist/scoped-plugin-registry.d.ts +7 -0
- package/dist/websocket/index.d.ts +1 -1
- package/dist/websocket/transport.d.ts +40 -18
- package/package.json +2 -2
- package/dist/plugins/chatgpt-oauth/ui/account-model.test.js +0 -69
- package/dist/plugins/local-accounts/ui/login-errors.test.ts +0 -22
- package/dist/plugins/token-stats/ui/client-model-search.test.ts +0 -58
- package/dist/plugins/token-stats/ui/pricing-catalog.test.ts +0 -114
|
@@ -17,6 +17,8 @@ export interface TrustedDataIdentity {
|
|
|
17
17
|
export declare const INTERNAL_DATA_IDENTITY_HEADER = "x-bungee-internal-data-identity";
|
|
18
18
|
export declare const INTERNAL_DATA_IDENTITY_MAC_HEADER = "x-bungee-internal-data-identity-mac";
|
|
19
19
|
export declare function getTrustedDataIdentity(request: Request): TrustedDataIdentity | null;
|
|
20
|
+
/** Core-only derivation: external headers cannot mint a logical generation identity. */
|
|
21
|
+
export declare function deriveWorkerRequestIdentity(source: Request, derived: Request, requestId: string): void;
|
|
20
22
|
export declare function signDataIdentity(identity: string, method: string, url: string, secret: string): string;
|
|
21
23
|
export declare function generateWorkerTransportSecret(): string;
|
|
22
24
|
export declare function parseWorkerTransportSecret(value: unknown): string;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
export interface DataAdmissionErrorDetails {
|
|
2
|
+
message?: string;
|
|
3
|
+
param?: string;
|
|
4
|
+
}
|
|
1
5
|
/** Shared inert error contract; importing it never loads admission runtime modules. */
|
|
2
6
|
export declare class DataAdmissionError extends Error {
|
|
3
7
|
readonly status: number;
|
|
4
8
|
readonly code: string;
|
|
5
9
|
readonly retryAfter?: number | undefined;
|
|
6
10
|
readonly name = "DataAdmissionError";
|
|
7
|
-
|
|
11
|
+
readonly details?: DataAdmissionErrorDetails;
|
|
12
|
+
constructor(status: number, code: string, retryAfter?: number | undefined, details?: DataAdmissionErrorDetails);
|
|
8
13
|
}
|
|
9
14
|
/** Plugin bundles have their own class identity; normalize their explicit error contract. */
|
|
10
15
|
export declare function normalizeAdmissionError(error: unknown): DataAdmissionError | null;
|
|
@@ -30,16 +30,23 @@ export interface GatewayDispatchTarget {
|
|
|
30
30
|
}
|
|
31
31
|
export interface DispatchRequestInput {
|
|
32
32
|
readonly context: import('../hooks').MutableRequestContext;
|
|
33
|
-
readonly targets: readonly
|
|
34
|
-
readonly protocol?: LLMProtocol;
|
|
35
|
-
})[];
|
|
33
|
+
readonly targets: readonly GatewayDispatchTarget[];
|
|
36
34
|
readonly principal?: import('../plugin-extensions').DataPrincipal;
|
|
37
35
|
readonly signal: AbortSignal;
|
|
38
36
|
readonly servingRevision?: number;
|
|
39
37
|
}
|
|
38
|
+
export interface DispatchConversionDiagnostic {
|
|
39
|
+
readonly param: string;
|
|
40
|
+
readonly action: 'mapped' | 'omitted';
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
}
|
|
40
43
|
export interface DispatchRequestDecision {
|
|
41
44
|
readonly target: GatewayDispatchTarget;
|
|
42
|
-
readonly
|
|
45
|
+
readonly protocol?: LLMProtocol;
|
|
46
|
+
readonly requiredUpstreamId?: string;
|
|
47
|
+
readonly adapter?: import('../plugin.types').Plugin; /** Canonical logical input after a protocol conversion; absent for native passthrough. */
|
|
48
|
+
readonly canonicalInput?: readonly unknown[];
|
|
49
|
+
readonly diagnostics?: readonly DispatchConversionDiagnostic[];
|
|
43
50
|
}
|
|
44
51
|
export interface GatewayDispatchInput extends Omit<DispatchRequestInput, 'targets'> {
|
|
45
52
|
readonly config: AppConfig;
|
|
@@ -51,7 +58,11 @@ export interface GatewayDispatchDecision {
|
|
|
51
58
|
readonly context: import('../hooks').MutableRequestContext;
|
|
52
59
|
readonly entryRouteId?: string;
|
|
53
60
|
readonly target?: GatewayDispatchTarget;
|
|
61
|
+
readonly requiredUpstreamId?: string;
|
|
62
|
+
readonly protocol?: LLMProtocol;
|
|
54
63
|
readonly adapter?: import('../plugin.types').Plugin;
|
|
64
|
+
readonly canonicalInput?: readonly unknown[];
|
|
65
|
+
readonly diagnostics?: readonly DispatchConversionDiagnostic[];
|
|
55
66
|
}
|
|
56
67
|
export interface GatewayRouteInput {
|
|
57
68
|
readonly request: Request;
|
|
@@ -30,6 +30,8 @@ export interface ProxyRequestResult {
|
|
|
30
30
|
transportFailureCode?: () => string | undefined;
|
|
31
31
|
}
|
|
32
32
|
export interface ProxyAttemptOptions {
|
|
33
|
+
readonly nativeWebSocket?: boolean;
|
|
34
|
+
readonly websocketBridge?: import('../websocket').WebSocketBridge;
|
|
33
35
|
readonly requestOverride?: GatewayRequestOverride;
|
|
34
36
|
readonly servingRevision?: number;
|
|
35
37
|
readonly attemptId: string;
|
package/dist/gateway/plugin.js
CHANGED
|
@@ -320,6 +320,7 @@ var init_impl = __esm(() => {
|
|
|
320
320
|
function createPluginHooks() {
|
|
321
321
|
return {
|
|
322
322
|
onGatewayWebSocket: new AsyncSeriesBailHook("onGatewayWebSocket"),
|
|
323
|
+
onWebSocketSessionMode: new AsyncSeriesBailHook("onWebSocketSessionMode"),
|
|
323
324
|
onWebSocketHandshake: new AsyncSeriesWaterfallHook("onWebSocketHandshake"),
|
|
324
325
|
onWebSocketObservation: new WebSocketObservationHook("onWebSocketObservation"),
|
|
325
326
|
onGatewayBody: new SyncBailHook("onGatewayBody"),
|
|
@@ -405,6 +406,13 @@ var init_plugin_extensions = __esm(() => {
|
|
|
405
406
|
});
|
|
406
407
|
|
|
407
408
|
// src/data-admission/errors.ts
|
|
409
|
+
function safeDetails(details) {
|
|
410
|
+
if (!details)
|
|
411
|
+
return;
|
|
412
|
+
const message = typeof details.message === "string" && details.message.length <= 512 && !/[\x00-\x1f\x7f]/.test(details.message) ? details.message : undefined;
|
|
413
|
+
const param = typeof details.param === "string" && details.param.length <= 256 && /^[a-zA-Z_$][\w.$\[\]-]*$/.test(details.param) ? details.param : undefined;
|
|
414
|
+
return message === undefined && param === undefined ? undefined : Object.freeze({ message, param });
|
|
415
|
+
}
|
|
408
416
|
function normalizeAdmissionError(error) {
|
|
409
417
|
if (error instanceof DataAdmissionError)
|
|
410
418
|
return error;
|
|
@@ -413,7 +421,7 @@ function normalizeAdmissionError(error) {
|
|
|
413
421
|
const value = error;
|
|
414
422
|
if (typeof value.status !== "number" || ![401, 403, 409, 422, 429, 503].includes(value.status) || typeof value.code !== "string" || !/^[a-zA-Z0-9_.-]{1,128}$/.test(value.code) || value.retryAfter !== undefined && (typeof value.retryAfter !== "number" || !Number.isFinite(value.retryAfter) || value.retryAfter < 0))
|
|
415
423
|
return null;
|
|
416
|
-
return new DataAdmissionError(value.status, value.code, value.retryAfter);
|
|
424
|
+
return new DataAdmissionError(value.status, value.code, value.retryAfter, value.details);
|
|
417
425
|
}
|
|
418
426
|
var DataAdmissionError;
|
|
419
427
|
var init_errors = __esm(() => {
|
|
@@ -422,11 +430,13 @@ var init_errors = __esm(() => {
|
|
|
422
430
|
code;
|
|
423
431
|
retryAfter;
|
|
424
432
|
name = "DataAdmissionError";
|
|
425
|
-
|
|
433
|
+
details;
|
|
434
|
+
constructor(status, code, retryAfter, details) {
|
|
426
435
|
super(code);
|
|
427
436
|
this.status = status;
|
|
428
437
|
this.code = code;
|
|
429
438
|
this.retryAfter = retryAfter;
|
|
439
|
+
this.details = safeDetails(details);
|
|
430
440
|
}
|
|
431
441
|
};
|
|
432
442
|
});
|
|
@@ -4,6 +4,12 @@ import type { ExpressionContext } from '../expression-engine';
|
|
|
4
4
|
import type { EffectiveRouteConfig, RuntimeUpstream } from '../worker/types';
|
|
5
5
|
export interface HandleRequestRuntimeContext {
|
|
6
6
|
servingRevision?: number;
|
|
7
|
+
/** Host-only session context, never accepted from client fields. */
|
|
8
|
+
transport?: 'websocket';
|
|
9
|
+
websocketBridge?: import('../websocket').WebSocketBridge;
|
|
10
|
+
skipEntryRate?: boolean;
|
|
11
|
+
/** Host session receives the codec's logical history without re-reading the request body. */
|
|
12
|
+
onCanonicalInput?: (input: readonly unknown[]) => void;
|
|
7
13
|
logging?: RequestLoggerDependencies;
|
|
8
14
|
}
|
|
9
15
|
type UpstreamSelector = (upstreams: RuntimeUpstream[], route?: EffectiveRouteConfig, context?: ExpressionContext) => RuntimeUpstream | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { GatewayWebSocketInput, WebSocketMessageView } from './websocket-contracts';
|
|
2
|
+
import type { ManagedWebSocketSession } from '../websocket';
|
|
3
|
+
import type { PluginHooks } from '../hooks';
|
|
4
|
+
/** One connection owns one active logical generation; the transport owns all queues. */
|
|
5
|
+
export declare class ResponsesWebSocketSession {
|
|
6
|
+
private readonly input;
|
|
7
|
+
private readonly hooks;
|
|
8
|
+
private active;
|
|
9
|
+
private readonly history;
|
|
10
|
+
private readonly historyLease;
|
|
11
|
+
private historyBytes;
|
|
12
|
+
constructor(input: GatewayWebSocketInput, hooks: PluginHooks);
|
|
13
|
+
dispose(): void;
|
|
14
|
+
private remember;
|
|
15
|
+
private error;
|
|
16
|
+
onMessage(session: ManagedWebSocketSession, message: WebSocketMessageView): void | Promise<void>;
|
|
17
|
+
private generate;
|
|
18
|
+
}
|
|
@@ -8,6 +8,7 @@ export declare function registerGatewayBuiltins(hooks: PluginHooks, plugins?: re
|
|
|
8
8
|
export declare function validateGatewayProviders(hooks: PluginHooks): void;
|
|
9
9
|
export declare function createGatewayHooks(plugins?: readonly Plugin[]): PluginHooks;
|
|
10
10
|
export declare function gatewayHooks(): PluginHooks;
|
|
11
|
+
export declare function runWithGatewayHooks<T>(hooks: PluginHooks, run: () => T): T;
|
|
11
12
|
export declare function initializeGateway(): void;
|
|
12
13
|
export declare function requireGatewayResult<T>(value: T | undefined, stage: string): T;
|
|
13
14
|
export declare const runGatewayRequest: typeof executeHttpRequest;
|
|
@@ -54,6 +54,7 @@ export interface GatewayWebSocketInput {
|
|
|
54
54
|
readonly bridge: import('../websocket').WebSocketBridge;
|
|
55
55
|
readonly config: import('@jeffusion/bungee-types').AppConfig;
|
|
56
56
|
readonly servingRevision: number;
|
|
57
|
+
readonly logging?: import('../logger/request-logger').RequestLoggerDependencies;
|
|
57
58
|
/** Host shutdown barrier; retains observer/credential owners until close cleanup. */
|
|
58
59
|
readonly retain: (completion: Promise<void>) => void;
|
|
59
60
|
}
|
|
@@ -184,9 +184,7 @@ export interface PluginScopeInfo {
|
|
|
184
184
|
export interface PluginInitContext {
|
|
185
185
|
/** Host-controlled, dependency-restricted public service facade. */
|
|
186
186
|
readonly services?: PluginServices;
|
|
187
|
-
readonly dispatchTargets?: readonly
|
|
188
|
-
readonly protocol?: import('@jeffusion/bungee-types').LLMProtocol;
|
|
189
|
-
})[];
|
|
187
|
+
readonly dispatchTargets?: readonly import('../gateway/contracts').GatewayDispatchTarget[];
|
|
190
188
|
/** 插件配置 */
|
|
191
189
|
config: Record<string, any>;
|
|
192
190
|
/** 插件存储 */
|
|
@@ -229,6 +227,7 @@ export declare function createPluginHooks(): PluginHooks;
|
|
|
229
227
|
*/
|
|
230
228
|
export interface PluginHooks {
|
|
231
229
|
onGatewayWebSocket: AsyncSeriesBailHook<[GatewayWebSocketInput], GatewayWebSocketResult>;
|
|
230
|
+
onWebSocketSessionMode: AsyncSeriesBailHook<[URL], 'responses'>;
|
|
232
231
|
onWebSocketHandshake: AsyncSeriesWaterfallHook<WebSocketHandshakeContext>;
|
|
233
232
|
onWebSocketObservation: WebSocketObservationHook;
|
|
234
233
|
onGatewayBody: SyncBailHook<GatewayBodyArguments, BodySource>;
|
|
@@ -100,8 +100,8 @@ export declare const accessLogWriter: {
|
|
|
100
100
|
getDatabase: () => Database;
|
|
101
101
|
updateResponseBodyId: (requestId: string, respBodyId: string) => void;
|
|
102
102
|
updateBodyId: (requestId: string, type: "request" | "response" | "original-request", bodyId: string) => void;
|
|
103
|
-
updateProtocolOutcome: (requestId: string, outcome: "
|
|
104
|
-
updateTransportOutcome: (requestId: string, outcome: "
|
|
103
|
+
updateProtocolOutcome: (requestId: string, outcome: "completed" | "failed" | "cancelled" | "incomplete", success: boolean, code?: string | undefined, diagnosticMessage?: string | undefined) => void;
|
|
104
|
+
updateTransportOutcome: (requestId: string, outcome: "unknown" | "completed" | "failed" | "cancelled" | "pending", code?: string | undefined) => void;
|
|
105
105
|
flush: () => Promise<void>;
|
|
106
106
|
close: () => Promise<void>;
|
|
107
107
|
};
|