@elsium-ai/gateway 0.2.2 → 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.
@@ -0,0 +1,24 @@
1
+ import type { CompletionRequest, LLMResponse } from '@elsium-ai/core';
2
+ import type { Gateway } from './gateway';
3
+ export interface BatchConfig {
4
+ concurrency?: number;
5
+ retryPerItem?: number;
6
+ onProgress?: (completed: number, total: number) => void;
7
+ signal?: AbortSignal;
8
+ }
9
+ export interface BatchResultItem {
10
+ index: number;
11
+ success: boolean;
12
+ response?: LLMResponse;
13
+ error?: string;
14
+ }
15
+ export interface BatchResult {
16
+ results: BatchResultItem[];
17
+ totalSucceeded: number;
18
+ totalFailed: number;
19
+ totalDurationMs: number;
20
+ }
21
+ export declare function createBatch(gateway: Gateway, config?: BatchConfig): {
22
+ execute(requests: CompletionRequest[]): Promise<BatchResult>;
23
+ };
24
+ //# sourceMappingURL=batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAErE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAIxC,MAAM,WAAW,WAAW;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvD,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,WAAW,CAC1B,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,WAAW,GAClB;IAAE,OAAO,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CAAE,CAiGlE"}
@@ -0,0 +1,26 @@
1
+ import type { LLMResponse, Middleware, MiddlewareContext } from '@elsium-ai/core';
2
+ export interface CacheAdapter {
3
+ get(key: string): Promise<LLMResponse | null>;
4
+ set(key: string, value: LLMResponse, ttlMs: number): Promise<void>;
5
+ delete(key: string): Promise<void>;
6
+ clear(): Promise<void>;
7
+ }
8
+ export interface CacheStats {
9
+ hits: number;
10
+ misses: number;
11
+ size: number;
12
+ hitRate: number;
13
+ }
14
+ export interface CacheMiddlewareConfig {
15
+ adapter?: CacheAdapter;
16
+ ttlMs?: number;
17
+ maxSize?: number;
18
+ keyFn?: (ctx: MiddlewareContext) => string;
19
+ shouldCache?: (ctx: MiddlewareContext, response: LLMResponse) => boolean;
20
+ }
21
+ export declare function createInMemoryCache(maxSize?: number): CacheAdapter;
22
+ export declare function cacheMiddleware(config?: CacheMiddlewareConfig): Middleware & {
23
+ readonly adapter: CacheAdapter;
24
+ stats(): CacheStats;
25
+ };
26
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAKjF,MAAM,WAAW,YAAY;IAC5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACrC,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,MAAM,CAAA;IAC1C,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,EAAE,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAA;CACxE;AAOD,wBAAgB,mBAAmB,CAAC,OAAO,SAAO,GAAG,YAAY,CAuChE;AAmBD,wBAAgB,eAAe,CAC9B,MAAM,CAAC,EAAE,qBAAqB,GAC5B,UAAU,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAAC,KAAK,IAAI,UAAU,CAAA;CAAE,CA8CtE"}
package/dist/gateway.d.ts CHANGED
@@ -13,6 +13,8 @@ export interface GatewayConfig {
13
13
  xray?: boolean | {
14
14
  maxHistory?: number;
15
15
  };
16
+ maxMessages?: number;
17
+ maxInputTokens?: number;
16
18
  }
17
19
  export interface Gateway {
18
20
  complete(request: CompletionRequest): Promise<LLMResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,WAAW,EACX,UAAU,EAEV,cAAc,EACd,QAAQ,EACR,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAe,KAAK,YAAY,EAAiC,MAAM,iBAAiB,CAAA;AAC/F,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAI5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM7C,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACxC;AAED,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAA;IAChD,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG;QAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC;QAC3E,IAAI,EAAE,CAAC,CAAA;QACP,QAAQ,EAAE,WAAW,CAAA;KACrB,CAAC,CAAA;IACF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAA;CACvC;AAQD,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,WAAW,GAC9C,IAAI,CAEN;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CA6JtD"}
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,WAAW,EACX,UAAU,EAEV,cAAc,EAEd,QAAQ,EACR,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAI5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM7C,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAA;IAChD,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG;QAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC;QAC3E,IAAI,EAAE,CAAC,CAAA;QACP,QAAQ,EAAE,WAAW,CAAA;KACrB,CAAC,CAAA;IACF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAA;CACvC;AAQD,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,WAAW,GAC9C,IAAI,CAEN;AAiID,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CA0ItD"}
package/dist/index.d.ts CHANGED
@@ -11,7 +11,13 @@ export { securityMiddleware, detectPromptInjection, detectJailbreak, redactSecre
11
11
  export type { SecurityMiddlewareConfig, SecurityViolation, SecurityResult, DataClassification, ClassificationResult, } from './security';
12
12
  export { createBulkhead, bulkheadMiddleware } from './bulkhead';
13
13
  export type { BulkheadConfig, Bulkhead } from './bulkhead';
14
+ export { cacheMiddleware, createInMemoryCache } from './cache';
15
+ export type { CacheAdapter, CacheStats, CacheMiddlewareConfig } from './cache';
16
+ export { outputGuardrailMiddleware } from './output-guardrails';
17
+ export type { OutputGuardrailConfig, OutputGuardrailRule, OutputViolation, } from './output-guardrails';
14
18
  export { calculateCost, registerPricing } from './pricing';
19
+ export { createBatch } from './batch';
20
+ export type { BatchConfig, BatchResult, BatchResultItem } from './batch';
15
21
  export { createProviderMesh } from './router';
16
22
  export type { ProviderMeshConfig, ProviderEntry, RoutingStrategy, ProviderMesh } from './router';
17
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAC5D,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGvD,YAAY,EACX,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,SAAS,GACT,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,wBAAwB,EACxB,mBAAmB,GACnB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACd,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAG7C,OAAO,EACN,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,eAAe,GACf,MAAM,YAAY,CAAA;AACnB,YAAY,EACX,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/D,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG1D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC7C,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAC5D,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGvD,YAAY,EACX,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,SAAS,GACT,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,wBAAwB,EACxB,mBAAmB,GACnB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACd,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAG7C,OAAO,EACN,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,eAAe,GACf,MAAM,YAAY,CAAA;AACnB,YAAY,EACX,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/D,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG1D,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAC9D,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAG9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,YAAY,EACX,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,GACf,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC7C,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -394,6 +394,94 @@ function createLogger(options = {}) {
394
394
  }
395
395
  };
396
396
  }
397
+ // ../core/src/schema.ts
398
+ var log = createLogger();
399
+ function zodDefKind(def) {
400
+ return typeof def.type === "string" ? def.type : def.typeName;
401
+ }
402
+ function zodObjectToJsonSchema(schema, convert) {
403
+ const shape = typeof schema.shape === "function" ? schema.shape() : schema.shape;
404
+ const properties = {};
405
+ const required = [];
406
+ for (const [key, value] of Object.entries(shape)) {
407
+ const fieldSchema = value;
408
+ properties[key] = convert(fieldSchema);
409
+ const fieldDef = fieldSchema._def;
410
+ const fieldKind = zodDefKind(fieldDef);
411
+ if (fieldKind !== "optional" && fieldKind !== "ZodOptional" && fieldKind !== "default" && fieldKind !== "ZodDefault") {
412
+ required.push(key);
413
+ }
414
+ if (fieldDef.description) {
415
+ properties[key].description = fieldDef.description;
416
+ }
417
+ }
418
+ return { type: "object", properties, required };
419
+ }
420
+ function zodToJsonSchema(schema) {
421
+ if (!("_def" in schema))
422
+ return { type: "object" };
423
+ const def = schema._def;
424
+ const kind = zodDefKind(def);
425
+ switch (kind) {
426
+ case "object":
427
+ case "ZodObject":
428
+ return zodObjectToJsonSchema(def, zodToJsonSchema);
429
+ case "string":
430
+ case "ZodString":
431
+ return { type: "string" };
432
+ case "number":
433
+ case "ZodNumber":
434
+ return { type: "number" };
435
+ case "boolean":
436
+ case "ZodBoolean":
437
+ return { type: "boolean" };
438
+ case "array":
439
+ case "ZodArray":
440
+ return {
441
+ type: "array",
442
+ items: zodToJsonSchema(def.element ?? def.type)
443
+ };
444
+ case "enum":
445
+ case "ZodEnum": {
446
+ const values = def.values ?? (def.entries ? Object.values(def.entries) : []);
447
+ return { type: "string", enum: values };
448
+ }
449
+ case "optional":
450
+ case "ZodOptional":
451
+ return zodToJsonSchema(def.innerType);
452
+ case "default":
453
+ case "ZodDefault":
454
+ return zodToJsonSchema(def.innerType);
455
+ case "nullable":
456
+ case "ZodNullable": {
457
+ const inner = zodToJsonSchema(def.innerType);
458
+ return { ...inner, nullable: true };
459
+ }
460
+ case "ZodLiteral":
461
+ return { type: typeof def.value, const: def.value };
462
+ case "ZodUnion": {
463
+ const options = def.options.map(zodToJsonSchema);
464
+ return { anyOf: options };
465
+ }
466
+ case "ZodRecord":
467
+ return {
468
+ type: "object",
469
+ additionalProperties: def.valueType ? zodToJsonSchema(def.valueType) : { type: "string" }
470
+ };
471
+ case "ZodTuple": {
472
+ const items = (def.items ?? []).map(zodToJsonSchema);
473
+ return { type: "array", prefixItems: items, minItems: items.length, maxItems: items.length };
474
+ }
475
+ case "ZodDate":
476
+ return { type: "string", format: "date-time" };
477
+ default:
478
+ log.warn(`zodToJsonSchema: unsupported type ${kind}, defaulting to string`);
479
+ return { type: "string" };
480
+ }
481
+ }
482
+ // ../core/src/registry.ts
483
+ var log2 = createLogger();
484
+ var BLOCKED_KEYS = new Set(["__proto__", "constructor", "prototype"]);
397
485
  // ../core/src/circuit-breaker.ts
398
486
  function defaultShouldCount(error) {
399
487
  if (error && typeof error === "object" && "retryable" in error) {
@@ -560,16 +648,16 @@ function composeMiddleware(middlewares) {
560
648
  };
561
649
  }
562
650
  function loggingMiddleware(logger) {
563
- const log = logger ?? createLogger({ level: "info" });
651
+ const log3 = logger ?? createLogger({ level: "info" });
564
652
  return async (ctx, next) => {
565
- log.info("LLM request", {
653
+ log3.info("LLM request", {
566
654
  provider: ctx.provider,
567
655
  model: ctx.model,
568
656
  traceId: ctx.traceId,
569
657
  messageCount: ctx.request.messages.length
570
658
  });
571
659
  const response = await next(ctx);
572
- log.info("LLM response", {
660
+ log3.info("LLM response", {
573
661
  provider: ctx.provider,
574
662
  model: ctx.model,
575
663
  traceId: ctx.traceId,
@@ -705,7 +793,7 @@ function xrayMiddleware(options = {}) {
705
793
  }
706
794
 
707
795
  // src/pricing.ts
708
- var log = createLogger();
796
+ var log3 = createLogger();
709
797
  var PRICING = {
710
798
  "claude-opus-4-6": { inputPerMillion: 15, outputPerMillion: 75 },
711
799
  "claude-sonnet-4-6": { inputPerMillion: 3, outputPerMillion: 15 },
@@ -743,7 +831,7 @@ function resolveModelName(model) {
743
831
  function calculateCost(model, usage) {
744
832
  const pricing = PRICING[resolveModelName(model)];
745
833
  if (!pricing) {
746
- log.warn(`Unknown model "${model}" — cost will be reported as $0. Register pricing with registerPricing().`);
834
+ log3.warn(`Unknown model "${model}" — cost will be reported as $0. Register pricing with registerPricing().`);
747
835
  return {
748
836
  inputCost: 0,
749
837
  outputCost: 0,
@@ -837,15 +925,33 @@ function createAnthropicProvider(config) {
837
925
  if (part.type === "text")
838
926
  return { type: "text", text: part.text };
839
927
  if (part.type === "image" && part.source?.type === "base64") {
928
+ const src = part.source;
840
929
  return {
841
930
  type: "image",
842
931
  source: {
843
932
  type: "base64",
844
- media_type: part.source.mediaType,
845
- data: part.source.data
933
+ media_type: src.mediaType,
934
+ data: src.data
846
935
  }
847
936
  };
848
937
  }
938
+ if (part.type === "document" && part.source) {
939
+ if (part.source.type === "base64") {
940
+ const src = part.source;
941
+ return {
942
+ type: "document",
943
+ source: {
944
+ type: "base64",
945
+ media_type: src.mediaType,
946
+ data: src.data
947
+ }
948
+ };
949
+ }
950
+ return { type: "text", text: "[document: url source not supported by Anthropic]" };
951
+ }
952
+ if (part.type === "audio") {
953
+ return { type: "text", text: "[audio content not supported by this provider]" };
954
+ }
849
955
  return { type: "text", text: "[unsupported content]" };
850
956
  }
851
957
  function formatMultipartContent(msg, role) {
@@ -954,6 +1060,16 @@ function createAnthropicProvider(config) {
954
1060
  const tools = formatTools(req.tools);
955
1061
  if (tools)
956
1062
  body.tools = tools;
1063
+ if (req.schema) {
1064
+ const jsonSchema = zodToJsonSchema(req.schema);
1065
+ const structuredTool = {
1066
+ name: "_structured_output",
1067
+ description: "Return structured output matching the required schema",
1068
+ input_schema: jsonSchema
1069
+ };
1070
+ body.tools = [...tools ?? [], structuredTool];
1071
+ body.tool_choice = { type: "tool", name: "_structured_output" };
1072
+ }
957
1073
  const startTime = performance.now();
958
1074
  const raw = await retry(async () => {
959
1075
  const controller = new AbortController;
@@ -1163,7 +1279,31 @@ function createGoogleProvider(config) {
1163
1279
  return { role, parts };
1164
1280
  }
1165
1281
  function formatGeminiMultipartContent(msg, role) {
1166
- const parts = msg.content.filter((p) => p.type === "text").map((p) => ({ text: p.text }));
1282
+ const parts = [];
1283
+ for (const p of msg.content) {
1284
+ if (p.type === "text") {
1285
+ parts.push({ text: p.text });
1286
+ } else if (p.type === "image") {
1287
+ const img = p;
1288
+ if (img.source.type === "base64") {
1289
+ parts.push({ inlineData: { mimeType: img.source.mediaType, data: img.source.data } });
1290
+ } else {
1291
+ parts.push({ fileData: { mimeType: "image/jpeg", fileUri: img.source.url } });
1292
+ }
1293
+ } else if (p.type === "audio" || p.type === "document") {
1294
+ const media = p;
1295
+ if (media.source.type === "base64") {
1296
+ parts.push({
1297
+ inlineData: { mimeType: media.source.mediaType, data: media.source.data }
1298
+ });
1299
+ } else {
1300
+ const urlSource = media.source;
1301
+ parts.push({
1302
+ fileData: { mimeType: "application/octet-stream", fileUri: urlSource.url }
1303
+ });
1304
+ }
1305
+ }
1306
+ }
1167
1307
  return { role, parts };
1168
1308
  }
1169
1309
  function formatMessages(messages) {
@@ -1260,6 +1400,10 @@ function createGoogleProvider(config) {
1260
1400
  config2.topP = req.topP;
1261
1401
  if (req.stopSequences?.length)
1262
1402
  config2.stopSequences = req.stopSequences;
1403
+ if (req.schema) {
1404
+ config2.responseMimeType = "application/json";
1405
+ config2.responseSchema = zodToJsonSchema(req.schema);
1406
+ }
1263
1407
  return config2;
1264
1408
  }
1265
1409
  function buildRequestBody(req) {
@@ -1338,7 +1482,8 @@ async function handleGoogleErrorResponse(response) {
1338
1482
  throw ElsiumError.authError("google");
1339
1483
  }
1340
1484
  if (response.status === 429) {
1341
- throw ElsiumError.rateLimit("google");
1485
+ const retryAfter = response.headers.get("retry-after");
1486
+ throw ElsiumError.rateLimit("google", retryAfter ? Number.parseInt(retryAfter) * 1000 : undefined);
1342
1487
  }
1343
1488
  throw ElsiumError.providerError(`Google API error ${response.status}: ${errorBody}`, {
1344
1489
  provider: "google",
@@ -1524,6 +1669,43 @@ function createOpenAIProvider(config) {
1524
1669
  }
1525
1670
  return openaiMsg;
1526
1671
  }
1672
+ function formatUserContent(msg) {
1673
+ if (typeof msg.content === "string")
1674
+ return msg.content;
1675
+ const parts = [];
1676
+ for (const part of msg.content) {
1677
+ if (part.type === "text") {
1678
+ parts.push({ type: "text", text: part.text });
1679
+ } else if (part.type === "image") {
1680
+ if (part.source.type === "base64") {
1681
+ const url = `data:${part.source.mediaType};base64,${part.source.data}`;
1682
+ parts.push({ type: "image_url", image_url: { url } });
1683
+ } else {
1684
+ parts.push({ type: "image_url", image_url: { url: part.source.url } });
1685
+ }
1686
+ } else if (part.type === "audio") {
1687
+ if (part.source.type === "base64") {
1688
+ const format = part.source.mediaType.split("/")[1] ?? "wav";
1689
+ parts.push({
1690
+ type: "input_audio",
1691
+ input_audio: { data: part.source.data, format }
1692
+ });
1693
+ } else {
1694
+ parts.push({ type: "text", text: "[audio: url source requires file upload]" });
1695
+ }
1696
+ } else if (part.type === "document") {
1697
+ if (part.source.type === "base64") {
1698
+ parts.push({
1699
+ type: "text",
1700
+ text: `[document: ${part.source.mediaType} content attached as base64]`
1701
+ });
1702
+ } else {
1703
+ parts.push({ type: "text", text: `[document: ${part.source.url}]` });
1704
+ }
1705
+ }
1706
+ }
1707
+ return parts;
1708
+ }
1527
1709
  function formatMessages(messages) {
1528
1710
  const formatted = [];
1529
1711
  for (const msg of messages) {
@@ -1539,7 +1721,7 @@ function createOpenAIProvider(config) {
1539
1721
  formatted.push(formatAssistantMessage(msg));
1540
1722
  continue;
1541
1723
  }
1542
- formatted.push({ role: "user", content: extractTextContent(msg) });
1724
+ formatted.push({ role: "user", content: formatUserContent(msg) });
1543
1725
  }
1544
1726
  return formatted;
1545
1727
  }
@@ -1616,6 +1798,17 @@ function createOpenAIProvider(config) {
1616
1798
  const tools = formatTools(req.tools);
1617
1799
  if (tools)
1618
1800
  body.tools = tools;
1801
+ if (req.schema) {
1802
+ const jsonSchema = zodToJsonSchema(req.schema);
1803
+ body.response_format = {
1804
+ type: "json_schema",
1805
+ json_schema: {
1806
+ name: "structured_output",
1807
+ strict: true,
1808
+ schema: jsonSchema
1809
+ }
1810
+ };
1811
+ }
1619
1812
  const startTime = performance.now();
1620
1813
  const raw = await retry(async () => {
1621
1814
  const controller = new AbortController;
@@ -1778,7 +1971,7 @@ var PROVIDER_FACTORIES = {
1778
1971
  function registerProviderFactory(name, factory) {
1779
1972
  PROVIDER_FACTORIES[name] = factory;
1780
1973
  }
1781
- function gateway(config) {
1974
+ function validateGatewayConfig(config) {
1782
1975
  const factory = PROVIDER_FACTORIES[config.provider];
1783
1976
  if (!factory) {
1784
1977
  throw new ElsiumError({
@@ -1787,21 +1980,92 @@ function gateway(config) {
1787
1980
  retryable: false
1788
1981
  });
1789
1982
  }
1983
+ if (typeof config.apiKey !== "string" || config.apiKey.trim() === "") {
1984
+ throw new ElsiumError({
1985
+ code: "CONFIG_ERROR",
1986
+ message: "apiKey must be a non-empty string",
1987
+ retryable: false
1988
+ });
1989
+ }
1990
+ if (config.timeout !== undefined && (!Number.isFinite(config.timeout) || config.timeout <= 0)) {
1991
+ throw new ElsiumError({
1992
+ code: "CONFIG_ERROR",
1993
+ message: "timeout must be a positive finite number",
1994
+ retryable: false
1995
+ });
1996
+ }
1997
+ if (config.maxRetries !== undefined && (!Number.isFinite(config.maxRetries) || !Number.isInteger(config.maxRetries) || config.maxRetries < 0)) {
1998
+ throw new ElsiumError({
1999
+ code: "CONFIG_ERROR",
2000
+ message: "maxRetries must be a non-negative finite integer",
2001
+ retryable: false
2002
+ });
2003
+ }
2004
+ return factory;
2005
+ }
2006
+ function autoRegisterProvider(provider) {
2007
+ if (!provider.metadata)
2008
+ return;
2009
+ registerProviderMetadata(provider.name, provider.metadata);
2010
+ if (!provider.metadata.pricing)
2011
+ return;
2012
+ for (const [model, pricing] of Object.entries(provider.metadata.pricing)) {
2013
+ registerPricing(model, pricing);
2014
+ }
2015
+ }
2016
+ function validateRequestLimits(request, maxMessages, maxInputTokens) {
2017
+ if (request.messages.length > maxMessages) {
2018
+ throw ElsiumError.validation(`Message count ${request.messages.length} exceeds limit of ${maxMessages}`);
2019
+ }
2020
+ let estimatedTokens = 0;
2021
+ for (const msg of request.messages) {
2022
+ const text = typeof msg.content === "string" ? msg.content : msg.content.map((p) => p.type === "text" ? p.text : "").join("");
2023
+ estimatedTokens += Math.ceil(text.length / 4);
2024
+ }
2025
+ if (estimatedTokens > maxInputTokens) {
2026
+ throw ElsiumError.validation(`Estimated input tokens (~${estimatedTokens}) exceeds limit of ${maxInputTokens}`);
2027
+ }
2028
+ }
2029
+ function buildMiddlewareContext(req, providerName, defaultModel, metadata) {
2030
+ return {
2031
+ request: req,
2032
+ provider: providerName,
2033
+ model: req.model ?? defaultModel,
2034
+ traceId: generateTraceId(),
2035
+ startTime: performance.now(),
2036
+ metadata
2037
+ };
2038
+ }
2039
+ async function accumulateStreamEvents(stream, emit) {
2040
+ let textContent = "";
2041
+ let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
2042
+ let stopReason = "end_turn";
2043
+ let id = "";
2044
+ for await (const event of stream) {
2045
+ emit(event);
2046
+ if (event.type === "text_delta") {
2047
+ textContent += event.text;
2048
+ } else if (event.type === "message_end") {
2049
+ usage = event.usage;
2050
+ stopReason = event.stopReason;
2051
+ } else if (event.type === "message_start") {
2052
+ id = event.id;
2053
+ }
2054
+ }
2055
+ return { textContent, usage, stopReason, id };
2056
+ }
2057
+ function gateway(config) {
2058
+ const factory = validateGatewayConfig(config);
1790
2059
  const provider = factory({
1791
2060
  apiKey: config.apiKey,
1792
2061
  baseUrl: config.baseUrl,
1793
2062
  timeout: config.timeout,
1794
2063
  maxRetries: config.maxRetries
1795
2064
  });
1796
- if (provider.metadata) {
1797
- registerProviderMetadata(provider.name, provider.metadata);
1798
- if (provider.metadata.pricing) {
1799
- for (const [model, pricing] of Object.entries(provider.metadata.pricing)) {
1800
- registerPricing(model, pricing);
1801
- }
1802
- }
1803
- }
2065
+ autoRegisterProvider(provider);
1804
2066
  const defaultModel = config.model ?? provider.defaultModel;
2067
+ const maxMessages = config.maxMessages ?? 1000;
2068
+ const maxInputTokens = config.maxInputTokens ?? 1e6;
1805
2069
  let xrayStore = null;
1806
2070
  const allMiddleware = [...config.middleware ?? []];
1807
2071
  if (config.xray) {
@@ -1816,14 +2080,7 @@ function gateway(config) {
1816
2080
  if (!composedMiddleware) {
1817
2081
  return provider.complete(req);
1818
2082
  }
1819
- const ctx = {
1820
- request: req,
1821
- provider: provider.name,
1822
- model: req.model ?? defaultModel,
1823
- traceId: generateTraceId(),
1824
- startTime: performance.now(),
1825
- metadata: request.metadata ?? {}
1826
- };
2083
+ const ctx = buildMiddlewareContext(req, provider.name, defaultModel, request.metadata ?? {});
1827
2084
  return composedMiddleware(ctx, async (c) => provider.complete(c.request));
1828
2085
  }
1829
2086
  return {
@@ -1835,34 +2092,27 @@ function gateway(config) {
1835
2092
  return xrayStore?.callHistory(limit) ?? [];
1836
2093
  },
1837
2094
  async complete(request) {
2095
+ validateRequestLimits(request, maxMessages, maxInputTokens);
1838
2096
  return executeWithMiddleware(request);
1839
2097
  },
1840
2098
  stream(request) {
2099
+ validateRequestLimits(request, maxMessages, maxInputTokens);
1841
2100
  const req = { ...request, model: request.model ?? defaultModel };
1842
2101
  if (composedMiddleware) {
1843
- const ctx = {
1844
- request: req,
1845
- provider: provider.name,
1846
- model: req.model ?? defaultModel,
1847
- traceId: generateTraceId(),
1848
- startTime: performance.now(),
1849
- metadata: request.metadata ?? {}
1850
- };
2102
+ const ctx = buildMiddlewareContext(req, provider.name, defaultModel, request.metadata ?? {});
1851
2103
  return createStream(async (emit) => {
1852
2104
  await composedMiddleware(ctx, async (c) => {
1853
- const stream = provider.stream(c.request);
1854
- for await (const event of stream) {
1855
- emit(event);
1856
- }
2105
+ const result = await accumulateStreamEvents(provider.stream(c.request), emit);
2106
+ const latencyMs = Math.round(performance.now() - ctx.startTime);
1857
2107
  return {
1858
- id: "",
1859
- message: { role: "assistant", content: "" },
1860
- usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
1861
- cost: { inputCost: 0, outputCost: 0, totalCost: 0, currency: "USD" },
2108
+ id: result.id,
2109
+ message: { role: "assistant", content: result.textContent },
2110
+ usage: result.usage,
2111
+ cost: calculateCost(c.model, result.usage),
1862
2112
  model: c.model,
1863
2113
  provider: provider.name,
1864
- stopReason: "end_turn",
1865
- latencyMs: 0,
2114
+ stopReason: result.stopReason,
2115
+ latencyMs,
1866
2116
  traceId: ctx.traceId
1867
2117
  };
1868
2118
  });
@@ -1872,107 +2122,46 @@ function gateway(config) {
1872
2122
  },
1873
2123
  async generate(request) {
1874
2124
  const { schema, ...rest } = request;
1875
- const jsonSchema = schemaToJsonSchema(schema);
1876
- const systemPrompt = [
1877
- rest.system ?? "",
1878
- "You MUST respond with valid JSON matching this schema:",
1879
- JSON.stringify(jsonSchema, null, 2),
1880
- "Respond ONLY with the JSON object, no markdown or explanation."
1881
- ].filter(Boolean).join(`
1882
-
1883
- `);
2125
+ const jsonSchema = zodToJsonSchema(schema);
1884
2126
  const response = await executeWithMiddleware({
1885
2127
  ...rest,
1886
- system: systemPrompt
2128
+ schema,
2129
+ system: [
2130
+ rest.system ?? "",
2131
+ "You MUST respond with valid JSON matching this schema:",
2132
+ JSON.stringify(jsonSchema, null, 2),
2133
+ "Respond ONLY with the JSON object, no markdown or explanation."
2134
+ ].filter(Boolean).join(`
2135
+
2136
+ `)
1887
2137
  });
1888
- const text = typeof response.message.content === "string" ? response.message.content : "";
1889
- const jsonMatch = text.match(/\{[\s\S]*\}/);
1890
- if (!jsonMatch) {
1891
- throw ElsiumError.validation("LLM response did not contain valid JSON", {
1892
- response: text
1893
- });
2138
+ let parsed;
2139
+ if (response.stopReason === "tool_use" && response.message.toolCalls?.length) {
2140
+ const structuredCall = response.message.toolCalls.find((tc) => tc.name === "_structured_output");
2141
+ if (structuredCall) {
2142
+ parsed = structuredCall.arguments;
2143
+ }
2144
+ }
2145
+ if (parsed === undefined) {
2146
+ const text = typeof response.message.content === "string" ? response.message.content : "";
2147
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
2148
+ if (!jsonMatch) {
2149
+ throw ElsiumError.validation("LLM response did not contain valid JSON", {
2150
+ response: text
2151
+ });
2152
+ }
2153
+ parsed = JSON.parse(jsonMatch[0]);
1894
2154
  }
1895
- const parsed = JSON.parse(jsonMatch[0]);
1896
2155
  const result = schema.safeParse(parsed);
1897
2156
  if (!result.success) {
1898
2157
  throw ElsiumError.validation("LLM response did not match schema", {
1899
- errors: result.error.issues,
1900
- response: text
2158
+ errors: result.error.issues
1901
2159
  });
1902
2160
  }
1903
2161
  return { data: result.data, response };
1904
2162
  }
1905
2163
  };
1906
2164
  }
1907
- function schemaToJsonSchema(schema) {
1908
- try {
1909
- if ("_def" in schema) {
1910
- const def = schema._def;
1911
- const result = convertZodDef(def);
1912
- if (result)
1913
- return result;
1914
- }
1915
- } catch {}
1916
- return { type: "string" };
1917
- }
1918
- function zodDefKind(def) {
1919
- return typeof def.type === "string" ? def.type : def.typeName;
1920
- }
1921
- function convertZodDef(def) {
1922
- const kind = zodDefKind(def);
1923
- switch (kind) {
1924
- case "object":
1925
- case "ZodObject":
1926
- return convertZodObject(def);
1927
- case "string":
1928
- case "ZodString":
1929
- return { type: "string" };
1930
- case "number":
1931
- case "ZodNumber":
1932
- return { type: "number" };
1933
- case "boolean":
1934
- case "ZodBoolean":
1935
- return { type: "boolean" };
1936
- case "array":
1937
- case "ZodArray":
1938
- return convertZodArray(def);
1939
- case "enum":
1940
- case "ZodEnum": {
1941
- const values = def.values ?? (def.entries ? Object.values(def.entries) : []);
1942
- return { type: "string", enum: values };
1943
- }
1944
- case "optional":
1945
- case "ZodOptional":
1946
- return convertZodOptional(def);
1947
- default:
1948
- return null;
1949
- }
1950
- }
1951
- function convertZodObject(def) {
1952
- if (!def.shape)
1953
- return null;
1954
- const shape = typeof def.shape === "function" ? def.shape() : def.shape;
1955
- const properties = {};
1956
- const required = [];
1957
- for (const [key, value] of Object.entries(shape)) {
1958
- properties[key] = schemaToJsonSchema(value);
1959
- const valDef = value._def;
1960
- const valKind = zodDefKind(valDef);
1961
- if (valKind !== "optional" && valKind !== "ZodOptional") {
1962
- required.push(key);
1963
- }
1964
- }
1965
- return { type: "object", properties, required };
1966
- }
1967
- function convertZodArray(def) {
1968
- return {
1969
- type: "array",
1970
- items: schemaToJsonSchema(def.element ?? def.type)
1971
- };
1972
- }
1973
- function convertZodOptional(def) {
1974
- return schemaToJsonSchema(def.innerType ?? def.innerType);
1975
- }
1976
2165
  // src/security.ts
1977
2166
  var INJECTION_PATTERNS = [
1978
2167
  {
@@ -2223,6 +2412,12 @@ function redactResponseSecrets(response, config) {
2223
2412
  }
2224
2413
  function securityMiddleware(config) {
2225
2414
  return async (ctx, next) => {
2415
+ if (ctx.request.system) {
2416
+ const sysViolations = scanMessageForViolations(ctx.request.system, config);
2417
+ if (sysViolations.length > 0) {
2418
+ reportAndThrow(sysViolations, config);
2419
+ }
2420
+ }
2226
2421
  for (const message of ctx.request.messages) {
2227
2422
  const text = extractText(message.content);
2228
2423
  if (!text)
@@ -2329,6 +2524,321 @@ function bulkheadMiddleware(config) {
2329
2524
  return bulkhead.execute(() => next(ctx));
2330
2525
  };
2331
2526
  }
2527
+ // src/cache.ts
2528
+ import { createHash } from "node:crypto";
2529
+ var log4 = createLogger();
2530
+ function createInMemoryCache(maxSize = 1000) {
2531
+ const cache = new Map;
2532
+ function evict() {
2533
+ if (cache.size <= maxSize)
2534
+ return;
2535
+ const firstKey = cache.keys().next().value;
2536
+ if (firstKey !== undefined)
2537
+ cache.delete(firstKey);
2538
+ }
2539
+ return {
2540
+ async get(key) {
2541
+ const entry = cache.get(key);
2542
+ if (!entry)
2543
+ return null;
2544
+ if (Date.now() > entry.expiresAt) {
2545
+ cache.delete(key);
2546
+ return null;
2547
+ }
2548
+ cache.delete(key);
2549
+ cache.set(key, entry);
2550
+ return entry.value;
2551
+ },
2552
+ async set(key, value, ttlMs) {
2553
+ cache.set(key, { value, expiresAt: Date.now() + ttlMs });
2554
+ evict();
2555
+ },
2556
+ async delete(key) {
2557
+ cache.delete(key);
2558
+ },
2559
+ async clear() {
2560
+ cache.clear();
2561
+ }
2562
+ };
2563
+ }
2564
+ function defaultCacheKey(ctx) {
2565
+ const data = JSON.stringify({
2566
+ provider: ctx.provider,
2567
+ model: ctx.model,
2568
+ messages: ctx.request.messages,
2569
+ system: ctx.request.system,
2570
+ temperature: ctx.request.temperature
2571
+ });
2572
+ return createHash("sha256").update(data).digest("hex");
2573
+ }
2574
+ function defaultShouldCache(_ctx, response) {
2575
+ const temp = _ctx.request.temperature;
2576
+ if (temp !== undefined && temp !== 0)
2577
+ return false;
2578
+ return response.stopReason === "end_turn";
2579
+ }
2580
+ function cacheMiddleware(config) {
2581
+ const ttlMs = config?.ttlMs ?? 3600000;
2582
+ const adapter = config?.adapter ?? createInMemoryCache(config?.maxSize ?? 1000);
2583
+ const keyFn = config?.keyFn ?? defaultCacheKey;
2584
+ const shouldCache = config?.shouldCache ?? defaultShouldCache;
2585
+ let hits = 0;
2586
+ let misses = 0;
2587
+ const middleware = async (ctx, next) => {
2588
+ if (ctx.request.stream) {
2589
+ return next(ctx);
2590
+ }
2591
+ const key = keyFn(ctx);
2592
+ const cached = await adapter.get(key);
2593
+ if (cached) {
2594
+ hits++;
2595
+ log4.debug("Cache hit", { key: key.slice(0, 8), provider: ctx.provider });
2596
+ return cached;
2597
+ }
2598
+ misses++;
2599
+ const response = await next(ctx);
2600
+ if (shouldCache(ctx, response)) {
2601
+ await adapter.set(key, response, ttlMs);
2602
+ }
2603
+ return response;
2604
+ };
2605
+ return Object.assign(middleware, {
2606
+ adapter,
2607
+ stats() {
2608
+ const total = hits + misses;
2609
+ return {
2610
+ hits,
2611
+ misses,
2612
+ size: 0,
2613
+ hitRate: total > 0 ? hits / total : 0
2614
+ };
2615
+ }
2616
+ });
2617
+ }
2618
+ // src/output-guardrails.ts
2619
+ var log5 = createLogger();
2620
+ var PII_PATTERNS2 = [
2621
+ {
2622
+ pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
2623
+ label: "email",
2624
+ replacement: "[REDACTED_EMAIL]"
2625
+ },
2626
+ {
2627
+ pattern: /(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
2628
+ label: "phone",
2629
+ replacement: "[REDACTED_PHONE]"
2630
+ },
2631
+ {
2632
+ pattern: /\b\d{3}-\d{2}-\d{4}\b/g,
2633
+ label: "ssn",
2634
+ replacement: "[REDACTED_SSN]"
2635
+ },
2636
+ {
2637
+ pattern: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,
2638
+ label: "credit_card",
2639
+ replacement: "[REDACTED_CC]"
2640
+ }
2641
+ ];
2642
+ var SECRET_PATTERNS2 = [
2643
+ {
2644
+ pattern: /\bsk-[A-Za-z0-9]{20,}\b/g,
2645
+ label: "api_key",
2646
+ replacement: "[REDACTED_API_KEY]"
2647
+ },
2648
+ {
2649
+ pattern: /\bpk-[A-Za-z0-9]{20,}\b/g,
2650
+ label: "api_key",
2651
+ replacement: "[REDACTED_API_KEY]"
2652
+ },
2653
+ {
2654
+ pattern: /\bAKIA[A-Z0-9]{16}\b/g,
2655
+ label: "aws_key",
2656
+ replacement: "[REDACTED_AWS_KEY]"
2657
+ }
2658
+ ];
2659
+ function detectPII(text) {
2660
+ const violations = [];
2661
+ const normalized = text.normalize("NFKC");
2662
+ for (const { pattern, label } of [...PII_PATTERNS2, ...SECRET_PATTERNS2]) {
2663
+ const regex = new RegExp(pattern.source, pattern.flags);
2664
+ if (regex.test(normalized)) {
2665
+ violations.push({
2666
+ type: "pii",
2667
+ detail: `Detected ${label} in output`,
2668
+ pattern: label
2669
+ });
2670
+ }
2671
+ }
2672
+ return violations;
2673
+ }
2674
+ function redactPII(text) {
2675
+ let result = text;
2676
+ for (const { pattern, replacement } of [...PII_PATTERNS2, ...SECRET_PATTERNS2]) {
2677
+ const regex = new RegExp(pattern.source, pattern.flags);
2678
+ result = result.replace(regex, replacement);
2679
+ }
2680
+ return result;
2681
+ }
2682
+ function checkContentPolicy(text, policy) {
2683
+ const violations = [];
2684
+ if (policy.maxResponseLength && text.length > policy.maxResponseLength) {
2685
+ violations.push({
2686
+ type: "content_policy",
2687
+ detail: `Response length ${text.length} exceeds max ${policy.maxResponseLength}`
2688
+ });
2689
+ }
2690
+ if (policy.blockedPatterns) {
2691
+ for (const pattern of policy.blockedPatterns) {
2692
+ if (pattern.test(text)) {
2693
+ violations.push({
2694
+ type: "content_policy",
2695
+ detail: `Response matches blocked pattern: ${pattern.source}`,
2696
+ pattern: pattern.source
2697
+ });
2698
+ }
2699
+ }
2700
+ }
2701
+ return violations;
2702
+ }
2703
+ function checkCustomRules(text, rules) {
2704
+ const violations = [];
2705
+ for (const rule of rules) {
2706
+ if (rule.pattern.test(text)) {
2707
+ violations.push({
2708
+ type: "custom_rule",
2709
+ detail: rule.message ?? `Output matched custom rule: ${rule.name}`,
2710
+ pattern: rule.pattern.source
2711
+ });
2712
+ }
2713
+ }
2714
+ return violations;
2715
+ }
2716
+ function outputGuardrailMiddleware(config) {
2717
+ const mode = config.onViolation ?? "block";
2718
+ return async (ctx, next) => {
2719
+ const response = await next(ctx);
2720
+ const text = extractText(response.message.content);
2721
+ const violations = [];
2722
+ if (config.piiDetection) {
2723
+ violations.push(...detectPII(text));
2724
+ }
2725
+ if (config.contentPolicy) {
2726
+ violations.push(...checkContentPolicy(text, config.contentPolicy));
2727
+ }
2728
+ if (config.customRules?.length) {
2729
+ violations.push(...checkCustomRules(text, config.customRules));
2730
+ }
2731
+ if (violations.length === 0)
2732
+ return response;
2733
+ for (const v of violations) {
2734
+ config.onViolationCallback?.(v);
2735
+ }
2736
+ switch (mode) {
2737
+ case "block":
2738
+ throw ElsiumError.validation(`Output guardrail violation: ${violations.map((v) => v.detail).join("; ")}`, { violations });
2739
+ case "redact": {
2740
+ let redacted = text;
2741
+ if (config.piiDetection) {
2742
+ redacted = redactPII(redacted);
2743
+ }
2744
+ return {
2745
+ ...response,
2746
+ message: { ...response.message, content: redacted }
2747
+ };
2748
+ }
2749
+ case "warn":
2750
+ log5.warn("Output guardrail violations detected", { violations });
2751
+ return response;
2752
+ }
2753
+ };
2754
+ }
2755
+ // src/batch.ts
2756
+ var log6 = createLogger();
2757
+ function createBatch(gateway2, config) {
2758
+ const concurrency = config?.concurrency ?? 5;
2759
+ const retryPerItem = config?.retryPerItem ?? 0;
2760
+ return {
2761
+ async execute(requests) {
2762
+ const startTime = performance.now();
2763
+ const results = new Array(requests.length);
2764
+ let completed = 0;
2765
+ let totalSucceeded = 0;
2766
+ let totalFailed = 0;
2767
+ let running = 0;
2768
+ let nextIndex = 0;
2769
+ const signal = config?.signal;
2770
+ async function processItem(index) {
2771
+ if (signal?.aborted) {
2772
+ results[index] = {
2773
+ index,
2774
+ success: false,
2775
+ error: "Batch cancelled"
2776
+ };
2777
+ totalFailed++;
2778
+ return;
2779
+ }
2780
+ let lastError;
2781
+ for (let attempt = 0;attempt <= retryPerItem; attempt++) {
2782
+ try {
2783
+ const response = await gateway2.complete(requests[index]);
2784
+ results[index] = { index, success: true, response };
2785
+ totalSucceeded++;
2786
+ return;
2787
+ } catch (err2) {
2788
+ lastError = err2 instanceof Error ? err2.message : String(err2);
2789
+ if (attempt < retryPerItem && err2 instanceof ElsiumError && err2.retryable) {
2790
+ continue;
2791
+ }
2792
+ break;
2793
+ }
2794
+ }
2795
+ results[index] = { index, success: false, error: lastError };
2796
+ totalFailed++;
2797
+ }
2798
+ return new Promise((resolve) => {
2799
+ function scheduleNext() {
2800
+ while (running < concurrency && nextIndex < requests.length) {
2801
+ if (signal?.aborted) {
2802
+ for (let i = nextIndex;i < requests.length; i++) {
2803
+ results[i] = { index: i, success: false, error: "Batch cancelled" };
2804
+ totalFailed++;
2805
+ }
2806
+ nextIndex = requests.length;
2807
+ break;
2808
+ }
2809
+ const idx = nextIndex++;
2810
+ running++;
2811
+ processItem(idx).then(() => {
2812
+ running--;
2813
+ completed++;
2814
+ config?.onProgress?.(completed, requests.length);
2815
+ if (completed === requests.length) {
2816
+ resolve({
2817
+ results,
2818
+ totalSucceeded,
2819
+ totalFailed,
2820
+ totalDurationMs: Math.round(performance.now() - startTime)
2821
+ });
2822
+ } else {
2823
+ scheduleNext();
2824
+ }
2825
+ });
2826
+ }
2827
+ }
2828
+ if (requests.length === 0) {
2829
+ resolve({
2830
+ results: [],
2831
+ totalSucceeded: 0,
2832
+ totalFailed: 0,
2833
+ totalDurationMs: 0
2834
+ });
2835
+ return;
2836
+ }
2837
+ scheduleNext();
2838
+ });
2839
+ }
2840
+ };
2841
+ }
2332
2842
  // src/router.ts
2333
2843
  var REASONING_KEYWORDS = /\b(prove|explain why|analyze|compare|contrast|evaluate|critique|debate|reason|deduce|infer|justify|argue|synthesize|hypothesize|derive)\b/i;
2334
2844
  var CODE_KEYWORDS = /\b(implement|refactor|debug|optimize|architect|design pattern|algorithm|data structure|write code|code review|fix the bug|type system)\b/i;
@@ -2557,7 +3067,22 @@ function createProviderMesh(config) {
2557
3067
  const available = sortedProviders.find((e) => isProviderAvailable(e.name));
2558
3068
  const entry = available ?? sortedProviders[0];
2559
3069
  const gw = getGateway(entry.name);
2560
- return gw.stream({ ...request, model: request.model ?? entry.model });
3070
+ let resolvedStream = null;
3071
+ callWithCircuitBreaker(entry.name, () => {
3072
+ resolvedStream = gw.stream({ ...request, model: request.model ?? entry.model });
3073
+ return Promise.resolve(resolvedStream);
3074
+ }).catch(() => {});
3075
+ if (resolvedStream === null) {
3076
+ const err2 = new ElsiumError({
3077
+ code: "PROVIDER_ERROR",
3078
+ message: "Circuit breaker is open",
3079
+ retryable: true
3080
+ });
3081
+ return new ElsiumStream(async function* () {
3082
+ yield { type: "error", error: err2 };
3083
+ }());
3084
+ }
3085
+ return resolvedStream;
2561
3086
  }
2562
3087
  };
2563
3088
  }
@@ -2569,6 +3094,7 @@ export {
2569
3094
  registerProvider,
2570
3095
  registerPricing,
2571
3096
  redactSecrets,
3097
+ outputGuardrailMiddleware,
2572
3098
  loggingMiddleware,
2573
3099
  listProviders,
2574
3100
  getProviderMetadata,
@@ -2578,13 +3104,16 @@ export {
2578
3104
  detectJailbreak,
2579
3105
  createProviderMesh,
2580
3106
  createOpenAIProvider,
3107
+ createInMemoryCache,
2581
3108
  createGoogleProvider,
2582
3109
  createBulkhead,
3110
+ createBatch,
2583
3111
  createAnthropicProvider,
2584
3112
  costTrackingMiddleware,
2585
3113
  composeMiddleware,
2586
3114
  classifyContent,
2587
3115
  checkBlockedPatterns,
2588
3116
  calculateCost,
3117
+ cacheMiddleware,
2589
3118
  bulkheadMiddleware
2590
3119
  };
@@ -0,0 +1,23 @@
1
+ import type { Middleware } from '@elsium-ai/core';
2
+ export interface OutputViolation {
3
+ type: 'pii' | 'content_policy' | 'custom_rule';
4
+ detail: string;
5
+ pattern?: string;
6
+ }
7
+ export interface OutputGuardrailRule {
8
+ name: string;
9
+ pattern: RegExp;
10
+ message?: string;
11
+ }
12
+ export interface OutputGuardrailConfig {
13
+ piiDetection?: boolean;
14
+ contentPolicy?: {
15
+ blockedPatterns?: RegExp[];
16
+ maxResponseLength?: number;
17
+ };
18
+ customRules?: OutputGuardrailRule[];
19
+ onViolation?: 'block' | 'redact' | 'warn';
20
+ onViolationCallback?: (violation: OutputViolation) => void;
21
+ }
22
+ export declare function outputGuardrailMiddleware(config: OutputGuardrailConfig): Middleware;
23
+ //# sourceMappingURL=output-guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-guardrails.d.ts","sourceRoot":"","sources":["../src/output-guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAKjD,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,KAAK,GAAG,gBAAgB,GAAG,aAAa,CAAA;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,qBAAqB;IACrC,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE;QACf,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACnC,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IACzC,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAA;CAC1D;AA+GD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,qBAAqB,GAAG,UAAU,CAiDnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EASnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA2C9C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAuT3E"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EAUnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA2C9C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAoV3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EASnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAmC9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAiPxE"}
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EAUnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAqC9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAiRxE"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EASnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAgD9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAmRxE"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,KAAK,cAAc,EAUnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAqD9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAqUxE"}
package/dist/router.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CompletionRequest, LLMResponse } from '@elsium-ai/core';
2
- import { type CircuitBreakerConfig, type ElsiumStream } from '@elsium-ai/core';
2
+ import { type CircuitBreakerConfig, ElsiumStream } from '@elsium-ai/core';
3
3
  export type RoutingStrategy = 'fallback' | 'cost-optimized' | 'latency-optimized' | 'capability-aware';
4
4
  export interface ProviderEntry {
5
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAEN,KAAK,oBAAoB,EAEzB,KAAK,YAAY,EAEjB,MAAM,iBAAiB,CAAA;AAKxB,MAAM,MAAM,eAAe,GACxB,UAAU,GACV,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,CAAA;AAErB,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,QAAQ,EAAE,eAAe,CAAA;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,cAAc,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAA;CAC/C;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAA;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CAClC;AAoDD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAoO3E"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAEN,KAAK,oBAAoB,EAEzB,YAAY,EAEZ,MAAM,iBAAiB,CAAA;AAKxB,MAAM,MAAM,eAAe,GACxB,UAAU,GACV,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,CAAA;AAErB,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,YAAY,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,QAAQ,EAAE,eAAe,CAAA;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,cAAc,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAA;CAC/C;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAA;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CAClC;AAoDD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAgQ3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,UAAU,EAAqC,MAAM,iBAAiB,CAAA;AAKjG,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,kBAAkB,GAAG,WAAW,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,OAAO,CAAA;IACb,UAAU,EAAE,iBAAiB,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,CAAA;IACpE,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACpD;AAuID,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CAAA;AAEtF,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,kBAAkB,CAAA;IACzB,aAAa,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA4BlE;AAQD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CASvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CASjE;AAoCD,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,GAClE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAYlD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAa1F;AAwDD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,UAAU,CAuB/E"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,UAAU,EAAqC,MAAM,iBAAiB,CAAA;AAKjG,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,kBAAkB,GAAG,WAAW,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,OAAO,CAAA;IACb,UAAU,EAAE,iBAAiB,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,CAAA;IACpE,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACpD;AAuID,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CAAA;AAEtF,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,kBAAkB,CAAA;IACzB,aAAa,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA4BlE;AAQD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CASvE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CASjE;AAoCD,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,GAClE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAYlD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAa1F;AAwDD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,UAAU,CA+B/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elsium-ai/gateway",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Multi-provider LLM gateway for ElsiumAI",
5
5
  "license": "MIT",
6
6
  "author": "Eric Utrera <ebutrera9103@gmail.com>",
@@ -26,7 +26,7 @@
26
26
  "dev": "bun --watch src/index.ts"
27
27
  },
28
28
  "dependencies": {
29
- "@elsium-ai/core": "^0.2.2",
29
+ "@elsium-ai/core": "^0.3.0",
30
30
  "zod": "^3.24.0"
31
31
  },
32
32
  "devDependencies": {