@jeffusion/bungee-core 5.19.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.
Files changed (41) hide show
  1. package/dist/config-worker/private-transport.d.ts +2 -0
  2. package/dist/data-admission/errors.d.ts +6 -1
  3. package/dist/gateway/contracts.d.ts +16 -3
  4. package/dist/gateway/forward-plugin.d.ts +2 -0
  5. package/dist/gateway/plugin.js +12 -2
  6. package/dist/gateway/request-plugin.d.ts +6 -0
  7. package/dist/gateway/responses-websocket-session.d.ts +18 -0
  8. package/dist/gateway/runtime.d.ts +1 -0
  9. package/dist/gateway/websocket-contracts.d.ts +1 -0
  10. package/dist/hooks/plugin-hooks.d.ts +2 -0
  11. package/dist/logger/access-log-writer.d.ts +2 -2
  12. package/dist/main.js +1234 -191
  13. package/dist/plugins/ai-transformer/index.js +11 -1
  14. package/dist/plugins/ai-transformer/index.js.map +5 -3
  15. package/dist/plugins/codex-router/control.js +677 -2
  16. package/dist/plugins/codex-router/control.js.map +19 -4
  17. package/dist/plugins/codex-router/index.js +4123 -33
  18. package/dist/plugins/codex-router/index.js.map +25 -7
  19. package/dist/plugins/codex-router/manifest.json +139 -9
  20. package/dist/plugins/key-access/index.js +12 -2
  21. package/dist/plugins/key-access/index.js.map +3 -3
  22. package/dist/plugins/key-access/ingress.js +12 -2
  23. package/dist/plugins/key-access/ingress.js.map +3 -3
  24. package/dist/plugins/openai-messages-to-chat/index.js +693 -543
  25. package/dist/plugins/openai-messages-to-chat/index.js.map +8 -4
  26. package/dist/plugins/token-metering/index.js +652 -71
  27. package/dist/plugins/token-metering/index.js.map +5 -3
  28. package/dist/plugins/token-stats/manifest.json +16 -6
  29. package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +13 -61
  30. package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +18 -74
  31. package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +3 -2
  32. package/dist/plugins/token-stats/ui/model-search.ts +2 -45
  33. package/dist/plugins/token-stats/ui/pricing-catalog.ts +2 -1
  34. package/dist/scoped-plugin-registry.d.ts +11 -2
  35. package/dist/websocket/index.d.ts +1 -1
  36. package/dist/websocket/transport.d.ts +40 -18
  37. package/package.json +2 -2
  38. package/dist/plugins/chatgpt-oauth/ui/account-model.test.js +0 -69
  39. package/dist/plugins/local-accounts/ui/login-errors.test.ts +0 -22
  40. package/dist/plugins/token-stats/ui/client-model-search.test.ts +0 -58
  41. 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
- constructor(status: number, code: string, retryAfter?: number | undefined);
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,15 +30,23 @@ export interface GatewayDispatchTarget {
30
30
  }
31
31
  export interface DispatchRequestInput {
32
32
  readonly context: import('../hooks').MutableRequestContext;
33
- readonly targets: readonly (GatewayDispatchTarget & {
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;
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[];
42
50
  }
43
51
  export interface GatewayDispatchInput extends Omit<DispatchRequestInput, 'targets'> {
44
52
  readonly config: AppConfig;
@@ -50,6 +58,11 @@ export interface GatewayDispatchDecision {
50
58
  readonly context: import('../hooks').MutableRequestContext;
51
59
  readonly entryRouteId?: string;
52
60
  readonly target?: GatewayDispatchTarget;
61
+ readonly requiredUpstreamId?: string;
62
+ readonly protocol?: LLMProtocol;
63
+ readonly adapter?: import('../plugin.types').Plugin;
64
+ readonly canonicalInput?: readonly unknown[];
65
+ readonly diagnostics?: readonly DispatchConversionDiagnostic[];
53
66
  }
54
67
  export interface GatewayRouteInput {
55
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;
@@ -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
- constructor(status, code, retryAfter) {
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,6 +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 import('../gateway/contracts').GatewayDispatchTarget[];
187
188
  /** 插件配置 */
188
189
  config: Record<string, any>;
189
190
  /** 插件存储 */
@@ -226,6 +227,7 @@ export declare function createPluginHooks(): PluginHooks;
226
227
  */
227
228
  export interface PluginHooks {
228
229
  onGatewayWebSocket: AsyncSeriesBailHook<[GatewayWebSocketInput], GatewayWebSocketResult>;
230
+ onWebSocketSessionMode: AsyncSeriesBailHook<[URL], 'responses'>;
229
231
  onWebSocketHandshake: AsyncSeriesWaterfallHook<WebSocketHandshakeContext>;
230
232
  onWebSocketObservation: WebSocketObservationHook;
231
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: "incomplete" | "cancelled" | "failed" | "completed", success: boolean, code?: string | undefined, diagnosticMessage?: string | undefined) => void;
104
- updateTransportOutcome: (requestId: string, outcome: "cancelled" | "unknown" | "failed" | "pending" | "completed", code?: string | undefined) => void;
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
  };