UNPKG

ai-sdk-guardrails

Version:

Input and output guardrails middleware for Vercel AI SDK.

5,146 lines 169 kB
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/advanced/index.ts
var advanced_exports = {};
__export(advanced_exports, {
  DEFAULT_DETECT_NORMALIZATION: () => DEFAULT_DETECT_NORMALIZATION,
  GuardrailViolationAbort: () => GuardrailViolationAbort,
  PII_PATTERNS: () => PII_PATTERNS,
  ToolParameterValidationError: () => ToolParameterValidationError,
  after: () => after,
  backoffPresets: () => presets,
  clearViolationHistory: () => clearViolationHistory,
  compositeBackoff: () => compositeBackoff,
  createAdaptivePrepareStep: () => createAdaptivePrepareStep,
  createConsoleDebugger: () => createConsoleDebugger,
  createContentFilterTransform: () => createContentFilterTransform,
  createDebugWrapper: () => createDebugWrapper,
  createDefaultBuildRetryParams: () => createDefaultBuildRetryParams,
  createFinishReasonEnhancement: () => createFinishReasonEnhancement,
  createGuardrailAbortController: () => createGuardrailAbortController,
  createGuardrailPrepareStep: () => createGuardrailPrepareStep,
  createGuardrailProviderMetadata: () => createGuardrailProviderMetadata,
  createGuardrailStreamTransform: () => createGuardrailStreamTransform,
  createGuardrailStreamTransformBuffered: () => createGuardrailStreamTransformBuffered,
  createGuardrailTransform: () => createGuardrailTransform,
  createHealthCheck: () => createHealthCheck,
  createMetricsCollector: () => createMetricsCollector,
  createPIIRedactionTransform: () => createPIIRedactionTransform,
  createPipeline: () => createPipeline,
  createTokenAwareGuardrailTransform: () => createTokenAwareGuardrailTransform,
  createTokenBudgetTransform: () => createTokenBudgetTransform,
  createToolAbortionController: () => createToolAbortionController,
  detectSystemPromptLeak: () => detectSystemPromptLeak,
  enhancedPromptInjectionDetector: () => enhancedPromptInjectionDetector,
  envDebugMode: () => envDebugMode,
  estimateTokenCount: () => estimateTokenCount,
  exponentialBackoff: () => exponentialBackoff,
  fixedBackoff: () => fixedBackoff,
  formatTraceAsJSON: () => formatTraceAsJSON,
  formatTraceForConsole: () => formatTraceForConsole,
  formatTraceSummary: () => formatTraceSummary,
  getGuardrailFinishReason: () => getGuardrailFinishReason,
  getViolationStats: () => getViolationStats,
  guardrailMiddleware: () => guardrailMiddleware,
  incrementalPromptInjectionDetector: () => incrementalPromptInjectionDetector,
  inputGuardrailsMiddleware: () => inputGuardrailsMiddleware,
  inputPipeline: () => inputPipeline,
  intentBasedInjectionDetector: () => intentBasedInjectionDetector,
  jitteredExponentialBackoff: () => jitteredExponentialBackoff,
  lenientEscalation: () => lenientEscalation,
  linearBackoff: () => linearBackoff,
  logExecutionSummary: () => logExecutionSummary,
  noBackoff: () => noBackoff,
  noopGuardrailMiddleware: () => noopGuardrailMiddleware,
  normalizeForDetection: () => normalizeForDetection,
  not: () => not,
  outputGuardrailsMiddleware: () => outputGuardrailsMiddleware,
  outputPipeline: () => outputPipeline,
  parallel: () => parallel,
  resolveDetectNormalization: () => resolveDetectNormalization,
  resolveRetryConfig: () => resolveRetryConfig,
  strictEscalation: () => strictEscalation,
  toolCallInjectionDetector: () => toolCallInjectionDetector,
  warnOnly: () => warnOnly,
  when: () => when,
  withFallback: () => withFallback,
  withGracePeriod: () => withGracePeriod,
  withGradualEnforcement: () => withGradualEnforcement,
  withRetry: () => withRetry,
  withToolParameterGuardrails: () => withToolParameterGuardrails,
  wrapToolWithAbortion: () => wrapToolWithAbortion
});
module.exports = __toCommonJS(advanced_exports);

// src/guardrails.ts
var import_ai = require("ai");

// src/errors.ts
var import_provider = require("@ai-sdk/provider");
var marker = "ai-sdk-guardrails.error";
var symbol = Symbol.for(marker);
var GuardrailsError = class extends import_provider.AISDKError {
  [symbol] = true;
  timestamp;
  metadata;
  constructor(name, message, metadata = {}, cause) {
    super({ name, message, cause });
    this.timestamp = /* @__PURE__ */ new Date();
    this.metadata = metadata;
  }
  /**
   * Convert the error to a serializable object for logging/reporting
   */
  toJSON() {
    return {
      name: this.name,
      code: this.code,
      message: this.message,
      timestamp: this.timestamp.toISOString(),
      metadata: this.metadata,
      stack: this.stack
    };
  }
  /**
   * Check if this error is of a specific guardrails error subclass.
   */
  is(errorClass) {
    return this instanceof errorClass;
  }
  /**
   * Checks whether the given value is a guardrails error, across package
   * versions (marker-based, like `AISDKError.isInstance`).
   */
  static isInstance(error) {
    return super.hasMarker(error, marker);
  }
};
var GuardrailTimeoutError = class extends GuardrailsError {
  code = "GUARDRAIL_TIMEOUT";
  guardrailName;
  timeoutMs;
  constructor(guardrailName, timeoutMs, metadata = {}) {
    const message = `Guardrail "${guardrailName}" timed out after ${timeoutMs}ms`;
    super("GuardrailTimeoutError", message, {
      ...metadata,
      guardrailName,
      timeoutMs
    });
    this.guardrailName = guardrailName;
    this.timeoutMs = timeoutMs;
  }
};
var GuardrailsInputError = class extends GuardrailsError {
  code = "INPUT_BLOCKED";
  blockedGuardrails;
  constructor(blockedGuardrails, metadata = {}) {
    const guardrailNames = blockedGuardrails.map((g) => g.name).join(", ");
    const message = `Input blocked by guardrail${blockedGuardrails.length > 1 ? "s" : ""}: ${guardrailNames}`;
    super("GuardrailsInputError", message, { ...metadata, blockedGuardrails });
    this.blockedGuardrails = blockedGuardrails;
  }
};
var GuardrailsOutputError = class extends GuardrailsError {
  code = "OUTPUT_BLOCKED";
  blockedGuardrails;
  constructor(blockedGuardrails, metadata = {}) {
    const guardrailNames = blockedGuardrails.map((g) => g.name).join(", ");
    const message = `Output blocked by guardrail${blockedGuardrails.length > 1 ? "s" : ""}: ${guardrailNames}`;
    super("GuardrailsOutputError", message, { ...metadata, blockedGuardrails });
    this.blockedGuardrails = blockedGuardrails;
  }
};

// src/spec.ts
var import_zod = require("zod");
var GuardrailSpec = class {
  constructor(name, description, mediaType, configSchema, checkFn, ctxRequirements, metadata) {
    this.name = name;
    this.description = description;
    this.mediaType = mediaType;
    this.configSchema = configSchema;
    this.checkFn = checkFn;
    this.ctxRequirements = ctxRequirements;
    this.metadata = metadata;
  }
  name;
  description;
  mediaType;
  configSchema;
  checkFn;
  ctxRequirements;
  metadata;
  /**
   * Return a JSON schema-like representation for tooling/SDKs.
   */
  schema() {
    return this.configSchema._def;
  }
  /**
   * Instantiate the guardrail with validated configuration.
   */
  instantiate(config) {
    const validated = this.configSchema instanceof import_zod.z.ZodType ? this.configSchema.parse(config ?? {}) : config;
    return new ConfiguredGuardrail(this, validated);
  }
};
var ConfiguredGuardrail = class {
  constructor(spec, config) {
    this.spec = spec;
    this.config = config;
  }
  spec;
  config;
  async ensureAsync(fn, ...args) {
    const result = fn(...args);
    if (result instanceof Promise) {
      return await result;
    }
    return result;
  }
  async run(context, input) {
    const startedAt = Date.now();
    try {
      const validatedContext = this.spec.ctxRequirements ? this.spec.ctxRequirements.parse(context) : context;
      const result = await this.ensureAsync(
        this.spec.checkFn,
        validatedContext,
        input,
        this.config
      );
      const info = result.info || {};
      if (!result.info) {
        info.guardrailName = this.spec.name;
        info.mediaType = this.spec.mediaType;
      }
      return {
        ...result,
        info: {
          ...info,
          guardrailName: this.spec.name,
          mediaType: this.spec.mediaType
        },
        context: {
          guardrailName: this.spec.name,
          guardrailVersion: this.spec.metadata?.version,
          executedAt: /* @__PURE__ */ new Date(),
          executionTimeMs: Date.now() - startedAt,
          ...result.context
        }
      };
    } catch (error) {
      return {
        tripwireTriggered: false,
        executionFailed: true,
        originalException: error instanceof Error ? error : new Error(String(error)),
        info: {
          guardrailName: this.spec.name,
          mediaType: this.spec.mediaType,
          error: error instanceof Error ? error.message : String(error)
        },
        message: error instanceof Error ? error.message : "Guardrail execution failed",
        severity: "high",
        context: {
          guardrailName: this.spec.name,
          executedAt: /* @__PURE__ */ new Date(),
          executionTimeMs: Date.now() - startedAt
        }
      };
    }
  }
};

// src/registry.ts
var import_zod2 = require("zod");
var NO_CONFIG = import_zod2.z.object({});
var NO_CONTEXT = import_zod2.z.object({});
var GuardrailRegistry = class {
  specs = /* @__PURE__ */ new Map();
  registerSpec(spec) {
    this.specs.set(spec.name, spec);
  }
  register(name, checkFn, description, mediaType = "text/plain", configSchema, ctxRequirements, metadata) {
    const spec = new GuardrailSpec(
      name,
      description,
      mediaType,
      configSchema || NO_CONFIG,
      checkFn,
      ctxRequirements || NO_CONTEXT,
      metadata
    );
    this.registerSpec(
      spec
    );
  }
  get(name) {
    return this.specs.get(name);
  }
  has(name) {
    return this.specs.has(name);
  }
  remove(name) {
    return this.specs.delete(name);
  }
  size() {
    return this.specs.size;
  }
  all() {
    return [...this.specs.values()];
  }
  list() {
    return this.all();
  }
  metadata() {
    return this.all().map((spec) => ({
      name: spec.name,
      description: spec.description,
      mediaType: spec.mediaType,
      hasConfig: spec.configSchema !== NO_CONFIG,
      hasContext: spec.ctxRequirements !== NO_CONTEXT,
      metadata: spec.metadata
    }));
  }
};
var defaultRegistry = new GuardrailRegistry();

// src/enhanced-runtime.ts
async function runGuardrails(input, bundle, context = {}, options = {}) {
  const {
    raiseGuardrailErrors = false,
    parallelExecution = true,
    timeoutMs,
    globalTimeoutMs,
    signal
  } = options;
  const startTime = Date.now();
  const guardrails = await instantiateGuardrails(bundle);
  if (signal?.aborted) {
    throw new Error("Guardrails execution aborted");
  }
  let results;
  if (parallelExecution) {
    const promises = guardrails.map(
      (guardrail) => runSingleGuardrail(guardrail, context, input, timeoutMs, signal)
    );
    results = globalTimeoutMs ? await Promise.race([
      Promise.all(promises),
      rejectAfter(
        globalTimeoutMs,
        `Global timeout of ${globalTimeoutMs}ms exceeded`
      )
    ]) : await Promise.all(promises);
  } else {
    results = [];
    for (const guardrail of guardrails) {
      if (globalTimeoutMs) {
        const elapsed = Date.now() - startTime;
        const remaining = globalTimeoutMs - elapsed;
        if (remaining <= 0) {
          throw new Error(`Global timeout of ${globalTimeoutMs}ms exceeded`);
        }
      }
      if (signal?.aborted) {
        throw new Error("Guardrails execution aborted");
      }
      const result = await runSingleGuardrail(
        guardrail,
        context,
        input,
        timeoutMs,
        signal
      );
      results.push(result);
      if (result.tripwireTriggered && result.severity === "critical") {
        break;
      }
    }
  }
  if (raiseGuardrailErrors) {
    const executionFailures = results.filter((r) => r.executionFailed);
    if (executionFailures.length > 0) {
      const firstFailure = executionFailures[0];
      if (firstFailure.originalException) {
        throw firstFailure.originalException;
      }
      throw new Error(firstFailure.message || "Guardrail execution failed");
    }
  }
  const totalExecutionTimeMs = Date.now() - startTime;
  const triggeredCount = results.filter((r) => r.tripwireTriggered).length;
  const failedCount = results.filter((r) => r.executionFailed).length;
  const successCount = results.length - failedCount;
  return {
    blocked: triggeredCount > 0,
    results,
    metadata: {
      totalExecutionTimeMs,
      triggeredCount,
      failedCount,
      successCount
    }
  };
}
async function runSingleGuardrail(guardrail, context, input, timeoutMs, signal) {
  try {
    if (signal?.aborted) {
      throw new Error("Execution aborted");
    }
    if (timeoutMs) {
      return await Promise.race([
        guardrail.run(context, input),
        rejectAfter(timeoutMs, `Guardrail timeout after ${timeoutMs}ms`)
      ]);
    }
    return await guardrail.run(context, input);
  } catch (error) {
    return {
      tripwireTriggered: false,
      executionFailed: true,
      originalException: error instanceof Error ? error : new Error(String(error)),
      info: {
        guardrailName: guardrail.spec.name,
        mediaType: guardrail.spec.mediaType,
        error: error instanceof Error ? error.message : String(error)
      },
      message: `Guardrail execution failed: ${error instanceof Error ? error.message : String(error)}`,
      severity: "high",
      context: {
        guardrailName: guardrail.spec.name,
        executedAt: /* @__PURE__ */ new Date()
      }
    };
  }
}
async function instantiateGuardrails(bundle) {
  const guardrails = [];
  for (const config of bundle.guardrails) {
    const spec = defaultRegistry.get(config.name);
    if (!spec) {
      throw new Error(`Guardrail '${config.name}' not found in registry`);
    }
    try {
      const guardrail = spec.instantiate(
        config.config || {}
      );
      guardrails.push(guardrail);
    } catch (error) {
      throw new Error(
        `Failed to instantiate guardrail '${config.name}': ${error instanceof Error ? error.message : String(error)}`,
        { cause: error }
      );
    }
  }
  return guardrails;
}
function rejectAfter(ms, message) {
  return new Promise(
    (_resolve, reject) => setTimeout(() => reject(new Error(message)), ms)
  );
}

// src/adapters/spec-adapter.ts
var import_zod3 = require("zod");
function guardrailToSpec(guardrail, options) {
  return new GuardrailSpec(
    guardrail.name,
    guardrail.description || `Guardrail: ${guardrail.name}`,
    "text/plain",
    import_zod3.z.unknown(),
    // Legacy guardrails don't expose config schemas
    async (context, input) => {
      const result = await guardrail.execute(input);
      return result;
    },
    void 0,
    {
      engine: "custom",
      version: guardrail.version,
      tags: guardrail.tags,
      category: "security",
      ...options?.metadata
    }
  );
}
function outputGuardrailToSpec(guardrail, options) {
  return new GuardrailSpec(
    guardrail.name,
    guardrail.description || `Output guardrail: ${guardrail.name}`,
    "text/plain",
    import_zod3.z.unknown(),
    // Placeholder schema for legacy guardrails
    async (context, input) => {
      const accumulatedText = context._accumulatedText;
      const result = await guardrail.execute(
        input,
        accumulatedText
      );
      return result;
    },
    void 0,
    {
      engine: "custom",
      version: guardrail.version,
      tags: guardrail.tags,
      category: "security",
      ...options?.metadata
    }
  );
}

// src/adapters/parallel-runtime-adapter.ts
async function executeInputGuardrailsWithEnhancedRuntime(guardrails, context, options = {}) {
  const specs = guardrails.filter((g) => g.enabled !== false).map((g) => guardrailToSpec(g));
  const bundle = {
    version: 1,
    stageName: "input",
    guardrails: specs.map((spec) => ({
      name: spec.name,
      config: {}
    }))
  };
  const tempRegistry = /* @__PURE__ */ new Map();
  for (const spec of specs) tempRegistry.set(spec.name, spec);
  const originalGet = defaultRegistry.get.bind(defaultRegistry);
  defaultRegistry.get = (name) => tempRegistry.get(name) || originalGet(name);
  try {
    const result = await runGuardrails(
      context,
      bundle,
      {},
      {
        parallelExecution: options.parallel ?? true,
        timeoutMs: options.timeout,
        raiseGuardrailErrors: !options.continueOnFailure,
        signal: options.signal
      }
    );
    defaultRegistry.get = originalGet;
    return result.results.map((r, index) => {
      const guardrail = guardrails[index];
      const guardrailName = guardrail?.name || "unknown";
      return {
        tripwireTriggered: r.tripwireTriggered,
        message: r.message,
        severity: r.severity,
        suggestion: r.suggestion,
        metadata: r.metadata || {},
        context: r.context?.guardrailName ? {
          guardrailName: r.context.guardrailName,
          guardrailVersion: r.context.guardrailVersion,
          executedAt: r.context.executedAt || /* @__PURE__ */ new Date(),
          executionTimeMs: r.context.executionTimeMs,
          environment: r.context.environment
        } : {
          guardrailName,
          executedAt: /* @__PURE__ */ new Date(),
          executionTimeMs: r.context?.executionTimeMs,
          environment: r.context?.environment
        }
      };
    });
  } catch (error) {
    defaultRegistry.get = originalGet;
    throw error;
  }
}
async function executeOutputGuardrailsWithEnhancedRuntime(guardrails, context, options = {}) {
  const specs = guardrails.filter((g) => g.enabled !== false).map(
    (g) => outputGuardrailToSpec(g)
  );
  const bundle = {
    version: 1,
    stageName: "output",
    guardrails: specs.map((spec) => ({
      name: spec.name,
      config: {}
    }))
  };
  const tempRegistry = /* @__PURE__ */ new Map();
  for (const spec of specs) tempRegistry.set(spec.name, spec);
  const originalGet = defaultRegistry.get.bind(defaultRegistry);
  defaultRegistry.get = (name) => tempRegistry.get(name) || originalGet(name);
  try {
    const runtimeContext = options.accumulatedText ? { _accumulatedText: options.accumulatedText } : {};
    const result = await runGuardrails(context, bundle, runtimeContext, {
      parallelExecution: options.parallel ?? true,
      timeoutMs: options.timeout,
      raiseGuardrailErrors: !options.continueOnFailure,
      signal: options.signal
    });
    defaultRegistry.get = originalGet;
    return result.results.map((r, index) => {
      const guardrail = guardrails[index];
      const guardrailName = guardrail?.name || "unknown";
      return {
        tripwireTriggered: r.tripwireTriggered,
        message: r.message,
        severity: r.severity,
        suggestion: r.suggestion,
        metadata: r.metadata || {},
        context: r.context?.guardrailName ? {
          guardrailName: r.context.guardrailName,
          guardrailVersion: r.context.guardrailVersion,
          executedAt: r.context.executedAt || /* @__PURE__ */ new Date(),
          executionTimeMs: r.context.executionTimeMs,
          environment: r.context.environment
        } : {
          guardrailName,
          executedAt: /* @__PURE__ */ new Date(),
          executionTimeMs: r.context?.executionTimeMs,
          environment: r.context?.environment
        }
      };
    });
  } catch (error) {
    defaultRegistry.get = originalGet;
    throw error;
  }
}
var V1_ENHANCED_RUNTIME_ENABLED = process.env.GUARDRAILS_ENHANCED_RUNTIME !== "false" && process.env.NODE_ENV !== "test";

// src/guardrails/internal.ts
var ENABLE_PERFORMANCE_TRACKING = process.env.NODE_ENV === "development" || process.env.GUARDRAILS_PERFORMANCE_TRACKING === "true";
var USE_ENHANCED_RUNTIME = process.env.GUARDRAILS_USE_ENHANCED_RUNTIME !== "false" && process.env.NODE_ENV !== "test";
function extractTextFromContent(content) {
  return content.filter((part) => part.type === "text").map((part) => part.text || "").join("");
}
var normalizedContextCache = /* @__PURE__ */ new WeakMap();
var TimeoutControllerPool = class {
  static controllers = [];
  static MAX_POOL_SIZE = 20;
  static acquire() {
    const controller = this.controllers.pop();
    if (controller && !controller.signal.aborted) {
      return controller;
    }
    return new AbortController();
  }
  static release(controller) {
    if (!controller.signal.aborted && this.controllers.length < this.MAX_POOL_SIZE) {
      this.controllers.push(controller);
    }
  }
  static clear() {
    this.controllers = [];
  }
};
function guardrailErrorResult(guardrailName, error, extra) {
  const errMsg = error instanceof Error ? error.message : String(error);
  const result = {
    tripwireTriggered: true,
    message: extra?.message ?? `Guardrail execution failed: ${errMsg}`,
    severity: "critical",
    metadata: extra?.metadata ?? { error: errMsg },
    info: {
      guardrailName,
      executionFailed: true,
      error: extra?.infoError ?? errMsg
    }
  };
  if (extra?.context) {
    result.context = extra.context;
  }
  return result;
}
var PRIORITY_ORDER = { critical: 4, high: 3, medium: 2, low: 1 };
function prepareGuardrails(guardrails) {
  return guardrails.filter((g) => g.enabled !== false).toSorted(
    (a, b) => (PRIORITY_ORDER[b.priority || "medium"] || 2) - (PRIORITY_ORDER[a.priority || "medium"] || 2)
  );
}
function createConditionalContext(guardrailName, guardrailVersion, executionTimeMs, existingContext) {
  if (!ENABLE_PERFORMANCE_TRACKING) {
    return {
      guardrailName,
      ...existingContext
    };
  }
  return {
    guardrailName,
    guardrailVersion,
    executedAt: /* @__PURE__ */ new Date(),
    executionTimeMs,
    ...existingContext
  };
}
function checkStreamStopCondition(stopConfig, violations) {
  if (stopConfig === true) {
    const criticalViolations = violations.filter(
      (v) => v.summary.blockedResults.some(
        (r) => (r.severity ?? "medium") === "critical"
      )
    );
    return violations.length >= 2 || criticalViolations.length > 0;
  }
  if (typeof stopConfig === "number") {
    return violations.length >= stopConfig;
  }
  if (typeof stopConfig === "function") {
    return stopConfig(violations);
  }
  return false;
}
async function executeWithOptimizedTimeout(execution, timeoutMs, errorMessage) {
  const controller = TimeoutControllerPool.acquire();
  let timeoutId;
  try {
    const timeoutPromise = new Promise((_, reject) => {
      timeoutId = setTimeout(() => {
        controller.abort();
        reject(new Error(errorMessage));
      }, timeoutMs);
    });
    const result = await Promise.race([
      execution(controller.signal),
      timeoutPromise
    ]);
    return result;
  } finally {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    TimeoutControllerPool.release(controller);
  }
}
function makeInvokeWithTimeout(invoke, timeoutMs) {
  return (guardrail) => executeWithOptimizedTimeout(
    (signal) => invoke(guardrail, signal),
    timeoutMs,
    `Guardrail ${guardrail.name} timed out after ${timeoutMs}ms`
  ).catch((error) => {
    if (error.message.includes("timed out")) {
      throw new GuardrailTimeoutError(guardrail.name, timeoutMs);
    }
    throw error;
  });
}
async function executeSequential(guardrails, invokeWithTimeout, opts) {
  const { continueOnFailure, logLevel, logger, label } = opts;
  const results = [];
  for (const guardrail of guardrails) {
    try {
      const result = await invokeWithTimeout(guardrail);
      results.push(result);
      if (result.tripwireTriggered) {
        if (logLevel !== "none") {
          logger.warn(
            `${label} guardrail "${guardrail.name}" triggered: ${result.message}`
          );
        }
        if (!continueOnFailure) {
          break;
        }
      }
    } catch (error) {
      if (logLevel !== "none") {
        logger.error(
          `Error executing ${label.toLowerCase()} guardrail "${guardrail.name}":`,
          error
        );
      }
      results.push(guardrailErrorResult(guardrail.name, error));
      if (!continueOnFailure) {
        break;
      }
    }
  }
  return results;
}
async function executeParallelPerGuardrail(guardrails, invokeWithTimeout, label, logLevel, logger) {
  return Promise.all(
    guardrails.map(async (guardrail) => {
      try {
        const result = await invokeWithTimeout(guardrail);
        if (result.tripwireTriggered && logLevel !== "none") {
          logger.warn(
            `${label} guardrail "${guardrail.name}" triggered: ${result.message}`
          );
        }
        return result;
      } catch (error) {
        if (logLevel !== "none") {
          logger.error(
            `Error executing ${label.toLowerCase()} guardrail "${guardrail.name}":`,
            error
          );
        }
        return guardrailErrorResult(guardrail.name, error);
      }
    })
  );
}
async function executeBatchInputGuardrails(guardrails, normalizedContext, timeoutMs, logLevel, logger) {
  if (guardrails.length === 0) return [];
  return executeWithOptimizedTimeout(
    async (signal) => {
      const results = await Promise.allSettled(
        guardrails.map(async (guardrail) => {
          try {
            return await guardrail.execute(normalizedContext, { signal });
          } catch (error) {
            if (logLevel !== "none") {
              logger.error(
                `Error executing input guardrail "${guardrail.name}":`,
                error
              );
            }
            return guardrailErrorResult(guardrail.name, error);
          }
        })
      );
      return results.map((result, index) => {
        const guardrail = guardrails[index];
        if (result.status === "fulfilled") {
          const guardResult = result.value;
          if (guardResult.tripwireTriggered && logLevel !== "none") {
            logger.warn(
              `Input guardrail "${guardrail.name}" triggered: ${guardResult.message}`
            );
          }
          return guardResult;
        }
        if (logLevel !== "none") {
          logger.error(
            `Input guardrail "${guardrail.name}" failed:`,
            result.reason
          );
        }
        return guardrailErrorResult(guardrail.name, result.reason);
      });
    },
    timeoutMs,
    `Batch guardrail execution timed out after ${timeoutMs}ms`
  ).catch((error) => {
    if (error.message.includes("timed out")) {
      return guardrails.map(
        (guardrail) => guardrailErrorResult(guardrail.name, error, {
          message: `Guardrail timed out after ${timeoutMs}ms`,
          metadata: { timeout: true },
          infoError: "Timeout"
        })
      );
    }
    throw error;
  });
}
function normalizeGuardrailContext(params) {
  const cached = normalizedContextCache.get(params);
  if (cached) {
    return cached;
  }
  const promptMessages = Array.isArray(params.prompt) ? params.prompt : [];
  const systemMessage = promptMessages.find((msg) => msg.role === "system");
  const system = systemMessage && Array.isArray(systemMessage.content) ? extractTextFromContent(systemMessage.content) : "";
  const messages = promptMessages.filter((msg) => msg.role !== "system").map((msg) => ({
    role: msg.role,
    content: msg.content && Array.isArray(msg.content) ? extractTextFromContent(msg.content) : ""
  }));
  const prompt = messages.length === 1 && messages[0]?.role === "user" ? messages[0].content : messages.map((m) => m.content).join(" ");
  const normalized = {
    prompt,
    messages,
    system,
    maxOutputTokens: params.maxOutputTokens,
    temperature: params.temperature,
    modelParams: {
      topP: params.topP,
      topK: params.topK,
      frequencyPenalty: params.frequencyPenalty,
      presencePenalty: params.presencePenalty,
      seed: params.seed,
      stopSequences: params.stopSequences
    }
  };
  normalizedContextCache.set(params, normalized);
  return normalized;
}
function toNormalizedGuardrailContext(params) {
  const candidate = params;
  if (typeof candidate.prompt === "string" && Array.isArray(candidate.messages)) {
    return params;
  }
  return normalizeGuardrailContext(params);
}
function createExecutionSummary(results, startTime) {
  const endTime = Date.now();
  const totalExecutionTime = endTime - startTime;
  const blockedResults = results.filter((r) => r.tripwireTriggered);
  const execTimes = results.map((r) => r.context?.executionTimeMs).filter((t) => typeof t === "number");
  const avgTime = execTimes.length > 0 ? execTimes.reduce((a, b) => a + b, 0) / execTimes.length : 0;
  const stats = {
    passed: results.filter((r) => !r.tripwireTriggered).length,
    blocked: blockedResults.length,
    failed: results.filter(
      (r) => r.severity === "critical" && r.tripwireTriggered
    ).length,
    averageExecutionTime: avgTime
  };
  return {
    allResults: results,
    blockedResults,
    totalExecutionTime,
    guardrailsExecuted: results.length,
    stats
  };
}
async function executeInputGuardrails(guardrails, params, options = {}) {
  const {
    parallel: parallel2 = true,
    timeout = 3e4,
    // 30 seconds
    continueOnFailure = true,
    logLevel = "warn",
    logger = console
  } = options;
  const enabledGuardrails = prepareGuardrails(guardrails);
  const invokeWithTimeout = makeInvokeWithTimeout(
    (guardrail, signal) => Promise.resolve(
      guardrail.execute(toNormalizedGuardrailContext(params), { signal })
    ),
    timeout
  );
  if (!parallel2) {
    return executeSequential(enabledGuardrails, invokeWithTimeout, {
      continueOnFailure,
      logLevel,
      logger,
      label: "Input"
    });
  }
  const runFallback = () => executeBatchInputGuardrails(
    enabledGuardrails,
    toNormalizedGuardrailContext(params),
    timeout,
    logLevel,
    logger
  );
  if (USE_ENHANCED_RUNTIME) {
    try {
      return await executeInputGuardrailsWithEnhancedRuntime(
        enabledGuardrails,
        toNormalizedGuardrailContext(params),
        { parallel: true, timeout, continueOnFailure }
      );
    } catch {
      return runFallback();
    }
  }
  return runFallback();
}
async function executeOutputGuardrails(guardrails, params, options = {}) {
  const {
    parallel: parallel2 = true,
    timeout = 3e4,
    // 30 seconds
    continueOnFailure = true,
    logLevel = "warn",
    logger = console,
    accumulatedText
  } = options;
  const enabledGuardrails = prepareGuardrails(guardrails);
  const invokeWithTimeout = makeInvokeWithTimeout(
    (guardrail, signal) => Promise.resolve(guardrail.execute(params, accumulatedText, { signal })),
    timeout
  );
  if (!parallel2) {
    return executeSequential(enabledGuardrails, invokeWithTimeout, {
      continueOnFailure,
      logLevel,
      logger,
      label: "Output"
    });
  }
  const runFallback = () => executeParallelPerGuardrail(
    enabledGuardrails,
    invokeWithTimeout,
    "Output",
    logLevel,
    logger
  );
  if (USE_ENHANCED_RUNTIME) {
    try {
      return await executeOutputGuardrailsWithEnhancedRuntime(
        enabledGuardrails,
        params,
        { parallel: true, timeout, continueOnFailure, accumulatedText }
      );
    } catch {
      return runFallback();
    }
  }
  return runFallback();
}

// src/core.ts
function createOutputGuardrail(name, execute) {
  return { name, execute };
}

// src/guardrails/output.ts
var EMPTY_CONTENT = {
  text: "",
  object: null,
  usage: void 0,
  finishReason: void 0,
  generationTimeMs: void 0,
  reasoningText: void 0
};
function emptyContent() {
  return { ...EMPTY_CONTENT };
}
function mapUsage(usage) {
  if (!usage) {
    return void 0;
  }
  const pickNumber = (keys) => {
    for (const key of keys) {
      const value = usage[key];
      if (typeof value === "number") {
        return value;
      }
      if (value && typeof value === "object" && "total" in value && typeof value.total === "number") {
        return value.total;
      }
    }
    return void 0;
  };
  const totalTokens = pickNumber(["totalTokens"]);
  const promptTokens = pickNumber(["inputTokens", "promptTokens"]);
  const completionTokens = pickNumber(["outputTokens", "completionTokens"]);
  const computedTotal = totalTokens ?? (promptTokens !== void 0 && completionTokens !== void 0 ? promptTokens + completionTokens : void 0);
  if (promptTokens === void 0 && completionTokens === void 0 && computedTotal === void 0) {
    return void 0;
  }
  return {
    promptTokens,
    completionTokens,
    totalTokens: computedTotal
  };
}
function extractGenerationTime(result) {
  return result.experimental_providerMetadata?.generationTimeMs ?? result.providerMetadata?.generationTimeMs ?? 0;
}
function extractReasoningText(result) {
  return result.reasoningText || result.experimental_providerMetadata?.reasoningText || void 0;
}
function createContent(partial) {
  return {
    ...EMPTY_CONTENT,
    ...partial
  };
}
function extractContent(result) {
  const contentArray = result.content;
  if ("content" in result && Array.isArray(contentArray) && contentArray.length > 0) {
    const typedResult = result;
    const textContent = typedResult.content.filter((item) => item.type === "text" && item.text).map((item) => item.text).join("");
    const objectValue = typedResult.output ?? typedResult.object ?? null;
    return createContent({
      text: textContent || "",
      object: objectValue,
      usage: mapUsage(typedResult.usage),
      finishReason: typedResult.finishReason,
      generationTimeMs: extractGenerationTime(typedResult),
      reasoningText: extractReasoningText(typedResult)
    });
  }
  if ("output" in result && result.output !== null && result.output !== void 0) {
    const outputResult = result;
    return createContent({
      text: outputResult.text || "",
      object: outputResult.output,
      usage: mapUsage(outputResult.usage),
      finishReason: outputResult.finishReason,
      generationTimeMs: extractGenerationTime(outputResult),
      reasoningText: extractReasoningText(outputResult)
    });
  }
  if ("object" in result && result.object !== null && result.object !== void 0) {
    const objectResult = result;
    return createContent({
      text: objectResult.text || "",
      object: objectResult.object,
      usage: mapUsage(objectResult.usage),
      finishReason: objectResult.finishReason,
      generationTimeMs: extractGenerationTime(objectResult),
      reasoningText: extractReasoningText(objectResult)
    });
  }
  if ("text" in result && typeof result.text === "string") {
    const textResult = result;
    return createContent({
      text: textResult.text || "",
      object: null,
      usage: mapUsage(textResult.usage),
      finishReason: textResult.finishReason,
      generationTimeMs: extractGenerationTime(textResult),
      reasoningText: extractReasoningText(textResult)
    });
  }
  if ("textStream" in result || "objectStream" in result || "embeddings" in result || "then" in result) {
    return emptyContent();
  }
  return emptyContent();
}
var secretRedaction = createOutputGuardrail(
  "secret-redaction",
  (context) => {
    const { text, object } = extractContent(context.result);
    const content = text || (object ? JSON.stringify(object) : "");
    const secretPatterns = [
      // API Keys (various formats) - more specific patterns to reduce false positives
      {
        name: "API Key",
        pattern: /(?:api[_-]?key|apikey|access[_-]?key)\s*[:=]\s*['"]?([a-zA-Z0-9]{20,})['"]?/gi
      },
      // AWS Access Keys
      {
        name: "AWS Access Key",
        pattern: /AKIA[0-9A-Z]{16}/g
      },
      // AWS Secret Keys
      {
        name: "AWS Secret Key",
        pattern: /[A-Za-z0-9/+=]{40}/g
      },
      // AWS ARNs
      {
        name: "AWS ARN",
        pattern: /arn:aws:[a-zA-Z0-9-]+:[a-zA-Z0-9-]*:[0-9]*:[a-zA-Z0-9-_/.:*]+/g
      },
      // JWT Tokens
      {
        name: "JWT Token",
        pattern: /eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g
      },
      // Bearer Tokens
      {
        name: "Bearer Token",
        pattern: /Bearer\s+[a-zA-Z0-9_.-]+/gi
      },
      // GitHub Personal Access Tokens
      {
        name: "GitHub Token",
        pattern: /ghp_[a-zA-Z0-9]{36}/g
      },
      // Google API Keys
      {
        name: "Google API Key",
        pattern: /AIza[0-9A-Za-z_-]{35}/g
      },
      // PEM Certificate/Key blocks
      {
        name: "PEM Certificate/Key",
        pattern: /-----BEGIN [A-Z ]+-----[\s\S]*?-----END [A-Z ]+-----/g
      },
      // SSH Private Keys
      {
        name: "SSH Private Key",
        pattern: /-----BEGIN (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----[\s\S]*?-----END (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/g
      },
      // Database Connection Strings
      {
        name: "Database Connection String",
        pattern: /(?:mongodb|postgres|mysql|redis):\/\/[^@\s]+:[^@\s]+@[^/\s]+/gi
      },
      // Environment variables with secrets (more specific to reduce false positives)
      {
        name: "Environment Secret",
        pattern: /(?:token|secret|password|key)\s*[:=]\s*['"]?([a-zA-Z0-9_.-]{16,})['"]?/gi
      }
    ];
    const detectedSecrets = [];
    for (const { name, pattern } of secretPatterns) {
      if (pattern.global) {
        pattern.lastIndex = 0;
      }
      let match;
      while ((match = pattern.exec(content)) !== null) {
        const maskedSecret = match[0].length > 20 ? match[0].slice(0, 8) + "..." + match[0].slice(-4) : match[0].slice(0, 4) + "...";
        detectedSecrets.push({
          type: name,
          pattern: maskedSecret,
          position: match.index
        });
        if (match[0].length === 0) {
          pattern.lastIndex++;
        }
      }
    }
    if (detectedSecrets.length > 0) {
      return {
        tripwireTriggered: true,
        message: `Output contains ${detectedSecrets.length} potential secret(s): ${detectedSecrets.map((s) => s.type).join(", ")}`,
        severity: "critical",
        metadata: {
          secretsDetected: detectedSecrets.length,
          secretTypes: detectedSecrets.map((s) => s.type),
          contentLength: content.length
        },
        suggestion: "Remove sensitive information before sharing output",
        info: {
          guardrailName: "secret-redaction",
          secretsDetected: detectedSecrets.length,
          secretTypes: detectedSecrets.map((s) => s.type),
          contentLength: content.length
        }
      };
    }
    return {
      tripwireTriggered: false,
      info: {
        guardrailName: "secret-redaction"
      }
    };
  }
);
var unsafeContentDetector = createOutputGuardrail(
  "unsafe-content-detector",
  (context) => {
    const { text, object } = extractContent(context.result);
    const content = text || (object ? JSON.stringify(object) : "");
    const unsafePatterns = [
      {
        category: "Violence",
        patterns: [
          /\b(kill|murder|assassinate|torture|bomb|weapon|gun|knife|explosive)\b/gi,
          /\b(harm|hurt|injure|attack|assault|fight)\s+(someone|people|person)/gi,
          /\b(violence|violent|aggression|aggressive)\b/gi
        ]
      },
      {
        category: "Hate Speech",
        patterns: [
          /\b(hate|racist|sexist|homophobic|transphobic|xenophobic)\b/gi,
          /\b(nazi|fascist|supremacist|terrorism|terrorist)\b/gi,
          /\b(discrimination|prejudice|bigotry)\b/gi
        ]
      },
      {
        category: "Self-Harm",
        patterns: [
          /\b(suicide|self-harm|self-hurt|cut myself|end my life)\b/gi,
          /\b(want to die|kill myself|harm myself)\b/gi,
          /\b(suicidal|depression|self-destruction)\b/gi
        ]
      },
      {
        category: "Illegal Activities",
        patterns: [
          /\b(illegal drugs|drug dealing|money laundering|fraud|scam)\b/gi,
          /\b(hack|crack|pirate|steal|burglary|theft)\b/gi,
          /\b(counterfeit|forgery|blackmail|extortion)\b/gi
        ]
      },
      {
        category: "Adult Content",
        patterns: [
          /\b(pornography|explicit sexual|adult content|nsfw)\b/gi,
          /\b(sexual explicit|graphic sexual|sexual imagery)\b/gi
        ]
      },
      {
        category: "Personal Information",
        patterns: [
          /\b\d{3}-\d{2}-\d{4}\b/g,
          // SSN format
          /\b\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b/g,
          // Credit card format
          /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g
          // Email
        ]
      }
    ];
    const detectedIssues = [];
    for (const { category, patterns } of unsafePatterns) {
      let totalMatches = 0;
      for (const pattern of patterns) {
        const matches = content.match(pattern);
        if (matches) {
          totalMatches += matches.length;
        }
      }
      if (totalMatches > 0) {
        detectedIssues.push({ category, matches: totalMatches });
      }
    }
    if (detectedIssues.length > 0) {
      return {
        tripwireTriggered: true,
        message: `Unsafe content detected: ${detectedIssues.map((i) => `${i.category} (${i.matches})`).join(", ")}`,
        severity: "high",
        metadata: {
          categoriesDetected: detectedIssues.length,
          issues: detectedIssues,
          contentLength: content.length
        },
        suggestion: "Review and modify content to remove potentially harmful material",
        info: {
          guardrailName: "unsafe-content-detector",
          categoriesDetected: detectedIssues.length,
          issues: detectedIssues,
          contentLength: content.length
        }
      };
    }
    return {
      tripwireTriggered: false,
      info: {
        guardrailName: "unsafe-content-detector"
      }
    };
  }
);

// src/guardrails/retry-helpers.ts
var SEVERITY_ORDER = {
  low: 1,
  medium: 2,
  high: 3,
  critical: 4
};
function findGuardrailForResult(result, guardrails) {
  const name = result.context?.guardrailName ?? result.info?.guardrailName;
  return guardrails.find((g) => g.name === name);
}
function getInstructionFromResult(result, guardrail, context) {
  if (guardrail?.getRetryInstruction) {
    const instruction = guardrail.getRetryInstruction({ ...context, result });
    if (typeof instruction === "string") {
      return { message: instruction };
    }
    return instruction ?? void 0;
  }
  if (result.message) {
    const suggestionPart = result.suggestion ? `. ${result.suggestion}` : "";
    return {
      message: `Please try again. The previous response was blocked: ${result.message}${suggestionPart}`
    };
  }
  return void 0;
}
function selectBlockedResults(summary, strategy) {
  const { blockedResults } = summary;
  if (blockedResults.length === 0) return [];
  switch (strategy) {
    case "first": {
      return [blockedResults[0]];
    }
    case "all": {
      return blockedResults;
    }
    default: {
      const sorted = [...blockedResults].toSorted((a, b) => {
        const severityA = SEVERITY_ORDER[a.severity ?? "medium"] ?? 2;
        const severityB = SEVERITY_ORDER[b.severity ?? "medium"] ?? 2;
        return severityB - severityA;
      });
      return [sorted[0]];
    }
  }
}
function combineInstructions(instructions) {
  if (instructions.length === 0) {
    return { message: "Please try again with a different approach." };
  }
  if (instructions.length === 1) {
    return instructions[0];
  }
  const combinedMessage = instructions.map((inst, i) => `${i + 1}. ${inst.message}`).join("\n");
  const tempAdjustments = instructions.map((i) => i.temperatureAdjustment).filter((t) => t !== void 0);
  const avgTempAdjustment = tempAdjustments.length > 0 ? tempAdjustments.reduce((a, b) => a + b, 0) / tempAdjustments.length : void 0;
  return {
    message: `Please address the following issues:
${combinedMessage}`,
    temperatureAdjustment: avgTempAdjustment,
    context: { combinedFrom: instructions.length }
  };
}
function createDefaultBuildRetryParams(options) {
  const {
    outputGuardrails,
    multipleBlockedStrategy = "highest-severity",
    attempt,
    maxRetries
  } = options;
  return ({ summary, originalParams, lastParams }) => {
    const selectedResults = selectBlockedResults(
      summary,
      multipleBlockedStrategy
    );
    const instructionContext = { attempt, maxRetries };
    const instructions = [];
    for (const result of selectedResults) {
      const guardrail = findGuardrailForResult(result, outputGuardrails);
      const instruction = getInstructionFromResult(
        result,
        guardrail,
        instructionContext
      );
      if (instruction) {
        instructions.push(instruction);
      }
    }
    const finalInstruction = combineInstructions(instructions);
    let newTemperature = lastParams.temperature ?? 0.7;
    if (finalInstruction.temperatureAdjustment !== void 0) {
      newTemperature = Math.max(
        0,
        Math.min(1, newTemperature + finalInstruction.temperatureAdjustment)
      );
    }
    const existingPrompt = Array.isArray(lastParams.prompt) ? lastParams.prompt : Array.isArray(originalParams.prompt) ? originalParams.prompt : [];
    return {
      ...lastParams,
      temperature: newTemperature,
      prompt: [
        ...existingPrompt,
        {
          role: "user",
          content: [{ type: "text", text: finalInstruction.message }]
        }
      ]
    };
  };
}
function resolveRetryConfig(globalRetry, blockedGuardrails) {
  let maxRetries = globalRetry?.maxRetries ?? 0;
  let backoffMs = globalRetry?.backoffMs ?? 0;
  if (maxRetries === 0) {
    for (const guardrail of blockedGuardrails) {
      if (guardrail.retry?.maxRetries !== void 0) {
        maxRetries = Math.max(maxRetries, guardrail.retry.maxRetries);
      }
      if (guardrail.retry?.backoffMs !== void 0 && backoffMs === 0) {
        backoffMs = guardrail.retry.backoffMs;
      }
    }
  }
  return { maxRetries, backoffMs };
}

// src/guardrails/generate-result-sync.ts
function joinTextFromContent(content) {
  if (!Array.isArray(content)) {
    return void 0;
  }
  const parts = content.filter(
    (part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string"
  ).map((part) => part.text);
  return parts.length > 0 ? parts.join("") : void 0;
}
function snapshotGenerateResultText(result) {
  const record = result;
  return {
    text: typeof record.text === "string" ? record.text : void 0,
    contentJoined: joinTextFromContent(record.content)
  };
}
function syncGenerateResultTextAfterGuardrails(result, before) {
  const record = result;
  const afterContent = joinTextFromContent(record.content);
  const afterText = typeof record.text === "string" ? record.text : void 0;
  const textChanged = afterText !== void 0 && afterText !== before.text;
  const contentChanged = afterContent !== void 0 && afterContent !== before.contentJoined;
  if (textChanged && !contentChanged && afterText !== void 0) {
    record.content = [{ type: "text", text: afterText }];
    record.text = afterText;
    return result;
  }
  if (contentChanged && afterContent !== void 0) {
    record.text = afterContent;
    return result;
  }
  if (afterContent !== void 0) {
    record.text = afterContent;
  } else if (afterText !== void 0) {
    record.content = [{ type: "text", text: afterText }];
  }
  return result;
}

// src/guardrails/middleware-factories.ts
var emptyV4Usage = {
  inputTokens: {
    total: 0,
    noCache: void 0,
    cacheRead: void 0,
    cacheWrite: void 0
  },
  outputTokens: {
    total: 0,
    text: void 0,
    reasoning: void 0
  }
};
var finishReasonStop = {
  unified: "stop",
  raw: void 0
};
var finishReasonOther = {
  unified: "other",
  raw: void 0
};
function inputGuardrailsMiddleware(config) {
  const {
    inputGuardrails,
    context,
    executionOptions = {},
    onInputBlocked,
    throwOnBlocked = false
  } = config;
  return {
    specificationVersion: "v4",
    transformParams: async ({
      params
    }) => {
      const baseContext = normalizeGuardrailContext(params);
      const guardrailContext = context ? { ...baseContext, requestContext: context } : baseContext;
      const executionStartTime = Date.now();
      const inputResults = await executeInputGuardrails(
        inputGuardrails,
        guardrailContext,
        executionOptions
      );
      const blockedResults = inputResults.filter((r) => r.tripwireTriggered);
      if (blockedResults.length > 0) {
        if (onInputBlocked) {
          const executionSummary = createExecutionSummary(
            inputResults,
            executionStartTime
          );
          onInputBlocked(executionSummary, guardrailContext);
        }
        if (throwOnBlocked) {
          const blockedGuardrails = blockedResults.map((r) => ({
            name: r.context?.guardrailName || "unknown",
            message: r.message || "Blocked",
            severity: r.severity || "medium"
          }));
          throw new GuardrailsInputError(blockedGuardrails);
        }
        const enhancedParams = params;
        enhancedParams.guardrailsBlocked = blockedResults;
        return enhancedParams;
      }
      return params;
    },
    wrapGenerate: async ({
      doGenerate,
      params
    }) => {
      const paramsWithGuardrails = params;
      if (paramsWithGuardrails.guardrailsBlocked) {
        const blockedResults = paramsWithGuardrails.guardrailsBlocked;
        const blockedMessage = blockedResults.map((r) => r.message).join(", ");
        const blockedText = `[Input blocked: ${blockedMessage}]`;
        return {
          text: blockedText,
          content: [{ type: "text", text: blockedText }],
          finishReason: finishReasonOther,
          usage: emptyV4Usage,
          warnings: [],
          rawCall: { rawPrompt: params.prompt, rawSettings: {} },
          response: { headers: {} }
        };
      }
      return doGenerate();
    },
    wrapStream: async ({
      doStream,
      params
    }) => {
      const paramsWithGuardrails = params;
      if (paramsWithGuardrails.guardrailsBlocked) {
        const blockedResults = paramsWithGuardrails.guardrailsBlocked;
        const blockedMessage = blockedResults.map((r) => r.message).join(", ");
        const stream = new ReadableStream({
          start(controller) {
            controller.enqueue({
              type: "text-delta",
              id: "1",
              delta: `[Input blocked: ${blockedMessage}]`
            });
            controller.enqueue({
              type: "finish",
              finishReason: finishReasonOther,
              usage: emptyV4Usage
            });
            controller.close();
          }
        });
        return { stream };
      }
      return doStream();
    }
  };
}
function outputGuardrailsMiddleware(config) {
  const {
    outputGuardrails,
    context,
    executionOptions = {},
    onOutputBlocked,
    throwOnBlocked = false,
    replaceOnBlocked = true,
    streamMode = "buffer",
    retry,
    stopOnGuardrailViolation
  } = config;
  return {
    specificationVersion: "v4",
    wrapGenerate: async ({
      doGenerate,
      params,
      model
    }) => {
      const result = await doGenerate();
      const resultTextBeforeGuardrails = snapshotGenerateResultText(result);
      const baseContext = normalizeGuardrailContext(params);
      const guardrailContext = context ? { ...baseContext, requestContext: context } : baseContext;
      const aiResult = result;
      const outputContext = {
        input: guardrailContext,
        result: aiResult
      };
      const startTime = Date.now();
      const outputResults = await executeOutputGuardrails(
        outputGuardrails,
        outputContext,
        executionOptions
      );
      const executionSummary = createExecutionSummary(
        outputResults,
        startTime
      );
      if (executionSummary.blockedResults.length > 0) {
        const blockedGuardrailObjects = executionSummary.blockedResults.map(
          (r) => outputGuardrails.find(
            (g) => g.name === (r.context?.guardrailName ?? r.info?.guardrailName)
          )
        ).filter((g) => g !== void 0);
        const effectiveRetry = resolveRetryConfig(
          retry,
          blockedGuardrailObjects
        );
        if (effectiveRetry.maxRetries > 0 && (retry?.onlyWhen ? retry.onlyWhen(executionSummary) : true)) {
          const maxRetries = effectiveRetry.maxRetries;
          let lastParams = params;
          let lastResult = result;
          for (let attempt = 1; attempt <= maxRetries; attempt++) {
            const wait = typeof effectiveRetry.backoffMs === "function" ? effectiveRetry.backoffMs(attempt) : effectiveRetry.backoffMs ?? 0;
            if (wait && wait > 0) {
              await new Promise((r) => setTimeout(r, wait));
            }
            const buildRetryParams = retry?.buildRetryParams ?? createDefaultBuildRetryParams({
              outputGuardrails,
              multipleBlockedStrategy: retry?.multipleBlockedStrategy ?? "highest-severity",
              attempt,
              maxRetries
            });
            const nextParams = buildRetryParams({
              summary: executionSummary,
              originalParams: params,
              lastParams,
              lastResult
            });
            const retryRaw = await model.doGenerate(nextParams);
            const retryTextBeforeGuardrails = snapshotGenerateResultText(retryRaw);
            const retryResult = retryRaw;
            const retryContext = {
              input: normalizeGuardrailContext(nextParams),
              result: retryResult
            };
            const retryStart = Date.now();
            const retryResults = await executeOutputGuardrails(
              outputGuardrails,
              retryContext,
              executionOptions
            );
            const retrySummary = createExecutionSummary(
              retryResults,
              retryStart
            );
            if (retrySummary.blockedResults.length === 0) {
              return syncGenerateResultTextAfterGuardrails(
                retryRaw,
                retryTextBeforeGuardrails
              );
            }
            lastParams = nextParams;
            lastResult = retryResult;
          }
        }
        if (onOutputBlocked) {
          onOutputBlocked(executionSummary, guardrailContext, result);
        }
        if (throwOnBlocked) {
          const blockedGuardrails = executionSummary.blockedResults.map(
            (r) => ({
              name: r.context?.guardrailName || "unknown",
              message: r.message || "Blocked",
              severity: r.severity || "medium"
            })
          );
          throw new GuardrailsOutputError(blockedGuardrails);
        }
        if (replaceOnBlocked) {
          const blockedMessage = executionSummary.blockedResults.map((r) => r.message).join(", ");
          const blockedText = `[Output blocked: ${blockedMessage}]`;
          const replaced = {
            ...result,
            text: blockedText,
            content: [{ type: "text", text: blockedText }]
          };
          return replaced;
        }
      }
      return syncGenerateResultTextAfterGuardrails(
        result,
        resultTextBeforeGuardrails
      );
    },
    wrapStream: async ({
      doStream,
      params,
      model
    }) => {
      const streamResult = await doStream();
      if (streamMode === "buffer") {
        let accumulatedText2 = "";
        let streamUsage;
        let streamFinishReason;
        const blockedChunks = [];
        const transformStream2 = new TransformStream({
          transform(chunk) {
            if (chunk.type === "text-delta") {
              const anyChunk = chunk;
              accumulatedText2 += anyChunk.delta ?? anyChunk.textDelta ?? "";
            } else if (chunk.type === "finish") {
              streamUsage = chunk.usage;
              streamFinishReason = chunk.finishReason;
            }
            blockedChunks.push(chunk);
          },
          async flush(controller) {
            const baseContext = normalizeGuardrailContext(params);
            const guardrailContext = context ? { ...baseContext, requestContext: context } : baseContext;
            const streamedResult = {
              text: accumulatedText2,
              content: [{ type: "text", text: accumulatedText2 }],
              usage: streamUsage,
              finishReason: streamFinishReason
            };
            const streamedTextBeforeGuardrails = snapshotGenerateResultText(streamedResult);
            const outputContext = {
              input: guardrailContext,
              result: streamedResult
            };
            const startTime = Date.now();
            const outputResults = await executeOutputGuardrails(
              outputGuardrails,
              outputContext,
              {
                ...executionOptions,
                accumulatedText: accumulatedText2
              }
            );
            const executionSummary = createExecutionSummary(
              outputResults,
              startTime
            );
            if (executionSummary.blockedResults.length > 0) {
              const blockedGuardrailObjects = executionSummary.blockedResults.map(
                (r) => outputGuardrails.find(
                  (g) => g.name === (r.context?.guardrailName ?? r.info?.guardrailName)
                )
              ).filter((g) => g !== void 0);
              const effectiveRetry = resolveRetryConfig(
                retry,
                blockedGuardrailObjects
              );
              if (effectiveRetry.maxRetries > 0 && (retry?.onlyWhen ? retry.onlyWhen(executionSummary) : true)) {
                const maxRetries = effectiveRetry.maxRetries;
                let lastParams = params;
                let lastResult = {
                  text: accumulatedText2
                };
                for (let attempt = 1; attempt <= maxRetries; attempt++) {
                  const wait = typeof effectiveRetry.backoffMs === "function" ? effectiveRetry.backoffMs(attempt) : effectiveRetry.backoffMs ?? 0;
                  if (wait && wait > 0) {
                    await new Promise((r) => setTimeout(r, wait));
                  }
                  const buildRetryParams = retry?.buildRetryParams ?? createDefaultBuildRetryParams({
                    outputGuardrails,
                    multipleBlockedStrategy: retry?.multipleBlockedStrategy ?? "highest-severity",
                    attempt,
                    maxRetries
                  });
                  const nextParams = buildRetryParams({
                    summary: executionSummary,
                    originalParams: params,
                    lastParams,
                    lastResult
                  });
                  const retryResult = await model.doGenerate(
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    nextParams
                  );
                  const retryContext = {
                    input: normalizeGuardrailContext(nextParams),
                    result: retryResult
                  };
                  const retryStart = Date.now();
                  const retryResults = await executeOutputGuardrails(
                    outputGuardrails,
                    retryContext,
                    executionOptions
                  );
                  const retrySummary = createExecutionSummary(
                    retryResults,
                    retryStart
                  );
                  if (retrySummary.blockedResults.length === 0) {
                    const { text: repairedText } = extractContent(
                      retryResult
                    );
                    controller.enqueue({
                      type: "text-delta",
                      id: "1",
                      delta: repairedText
                    });
                    controller.enqueue({
                      type: "finish",
                      finishReason: finishReasonStop,
                      usage: emptyV4Usage
                    });
                    return;
                  }
                  lastParams = nextParams;
                  lastResult = retryResult;
                }
              }
              if (onOutputBlocked) {
                onOutputBlocked(
                  executionSummary,
                  guardrailContext,
                  streamedResult
                );
              }
              if (throwOnBlocked) {
                controller.error(
                  new Error(
                    `Output guardrails blocked response: ${executionSummary.blockedResults.map((r) => r.message).join(", ")}`
                  )
                );
                return;
              }
              if (replaceOnBlocked) {
                const blockedMessage = executionSummary.blockedResults.map((r) => r.message).join(", ");
                controller.enqueue({
                  type: "text-delta",
                  id: "1",
                  delta: `[Output blocked: ${blockedMessage}]`
                });
                controller.enqueue({
                  type: "finish",
                  finishReason: finishReasonOther,
                  usage: emptyV4Usage
                });
              } else {
                for (const chunk of blockedChunks) {
                  controller.enqueue(chunk);
                }
              }
            } else {
              syncGenerateResultTextAfterGuardrails(
                streamedResult,
                streamedTextBeforeGuardrails
              );
              const finalText = typeof streamedResult.text === "string" ? streamedResult.text : accumulatedText2;
              if (finalText === accumulatedText2) {
                for (const chunk of blockedChunks) {
                  controller.enqueue(chunk);
                }
              } else {
                controller.enqueue({
                  type: "text-delta",
                  id: "1",
                  delta: finalText
                });
                controller.enqueue({
                  type: "finish",
                  finishReason: streamFinishReason ?? finishReasonStop,
                  usage: streamUsage ?? emptyV4Usage
                });
              }
            }
          }
        });
        return {
          stream: streamResult.stream.pipeThrough(
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            transformStream2
          )
        };
      }
      let accumulatedText = "";
      let blocked = false;
      let chunkIndex = 0;
      const streamViolationHistory = [];
      const transformStream = new TransformStream({
        async transform(chunk, controller) {
          if (blocked) {
            return;
          }
          if (chunk.type === "text-delta") {
            const anyChunk = chunk;
            accumulatedText += anyChunk.delta ?? anyChunk.textDelta ?? "";
            chunkIndex++;
            const baseContext = normalizeGuardrailContext(params);
            const guardrailContext = context ? { ...baseContext, requestContext: context } : baseContext;
            const outputContext = {
              input: guardrailContext,
              result: { text: accumulatedText }
            };
            const startTime = Date.now();
            const outputResults = await executeOutputGuardrails(
              outputGuardrails,
              outputContext,
              {
                ...executionOptions,
                accumulatedText
              }
            );
            const executionSummary = createExecutionSummary(
              outputResults,
              startTime
            );
            if (executionSummary.blockedResults.length > 0) {
              streamViolationHistory.push({
                chunkIndex,
                summary: executionSummary
              });
              const shouldStopEarly = stopOnGuardrailViolation && checkStreamStopCondition(
                stopOnGuardrailViolation,
                streamViolationHistory
              );
              if (shouldStopEarly) {
                blocked = true;
              }
              if (blocked) {
                if (onOutputBlocked) {
                  onOutputBlocked(executionSummary, guardrailContext, {
                    text: accumulatedText
                  });
                }
                if (throwOnBlocked) {
                  controller.error(
                    new Error(
                      `Output guardrails blocked response: ${executionSummary.blockedResults.map((r) => r.message).join(", ")}`
                    )
                  );
                  return;
                }
                if (replaceOnBlocked) {
                  const blockedMessage = executionSummary.blockedResults.map((r) => r.message).join(", ");
                  controller.enqueue({
                    type: "text-delta",
                    id: "1",
                    delta: `[Output blocked: ${blockedMessage}]`
                  });
                  controller.enqueue({
                    type: "finish",
                    finishReason: finishReasonOther,
                    usage: emptyV4Usage
                  });
                  return;
                }
              }
            }
            controller.enqueue(chunk);
          } else {
            controller.enqueue(chunk);
          }
        }
      });
      return {
        stream: streamResult.stream.pipeThrough(
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          transformStream
        )
      };
    }
  };
}

// src/guardrails.ts
async function runWithEnvelope(name, version, run) {
  const startTime = ENABLE_PERFORMANCE_TRACKING ? Date.now() : 0;
  try {
    const result = await run();
    const executionTime = ENABLE_PERFORMANCE_TRACKING ? Date.now() - startTime : void 0;
    return {
      ...result,
      context: createConditionalContext(
        name,
        version,
        executionTime,
        result.context
      )
    };
  } catch (error) {
    const executionTime = ENABLE_PERFORMANCE_TRACKING ? Date.now() - startTime : void 0;
    return guardrailErrorResult(name, error, {
      context: createConditionalContext(name, version, executionTime)
    });
  }
}
function defineInputGuardrail(guardrail) {
  const originalExecute = guardrail.execute;
  return {
    enabled: true,
    priority: "medium",
    version: "1.0.0",
    tags: [],
    ...guardrail,
    execute: (params, options) => runWithEnvelope(
      guardrail.name,
      guardrail.version,
      () => options === void 0 ? originalExecute(params) : originalExecute(params, options)
    )
  };
}

// src/guardrails/normalization.ts
var RE_WHITESPACE = /\s+/g;
var RE_WHITESPACE_SPLIT = /\s+/;
var RE_WORD_CHAR = /\w/;
var INVISIBLE_CHARS = /[\u00AD\u180E\u200B-\u200F\u2028-\u202F\u2060\uFEFF]/;
var RE_INVISIBLE = new RegExp(INVISIBLE_CHARS, "g");
var RE_REGEX_META = /[.*+?^${}()|[\]\\]/g;
var TYPO_MAP = {
  ingnore: "ignore",
  ignor: "ignore",
  ign0re: "ignore",
  previ0us: "previous",
  previus: "previous",
  instrucions: "instructions",
  instrucion: "instruction",
  overide: "override",
  overrride: "override",
  disreguard: "disregard",
  disrega: "disregard"
};
var HOMOGLYPH_MAP = [
  ["\uFF21", "A"],
  ["\uFF22", "B"],
  ["\uFF23", "C"],
  ["\uFF24", "D"],
  ["\uFF25", "E"],
  ["\uFF26", "F"],
  ["\uFF27", "G"],
  ["\uFF28", "H"],
  ["\uFF29", "I"],
  ["\uFF2A", "J"],
  ["\uFF2B", "K"],
  ["\uFF2C", "L"],
  ["\uFF2D", "M"],
  ["\uFF2E", "N"],
  ["\uFF2F", "O"],
  ["\uFF30", "P"],
  ["\uFF31", "Q"],
  ["\uFF32", "R"],
  ["\uFF33", "S"],
  ["\uFF34", "T"],
  ["\uFF35", "U"],
  ["\uFF36", "V"],
  ["\uFF37", "W"],
  ["\uFF38", "X"],
  ["\uFF39", "Y"],
  ["\uFF3A", "Z"],
  ["\uFF41", "a"],
  ["\uFF42", "b"],
  ["\uFF43", "c"],
  ["\uFF44", "d"],
  ["\uFF45", "e"],
  ["\uFF46", "f"],
  ["\uFF47", "g"],
  ["\uFF48", "h"],
  ["\uFF49", "i"],
  ["\uFF4A", "j"],
  ["\uFF4B", "k"],
  ["\uFF4C", "l"],
  ["\uFF4D", "m"],
  ["\uFF4E", "n"],
  ["\uFF4F", "o"],
  ["\uFF50", "p"],
  ["\uFF51", "q"],
  ["\uFF52", "r"],
  ["\uFF53", "s"],
  ["\uFF54", "t"],
  ["\uFF55", "u"],
  ["\uFF56", "v"],
  ["\uFF57", "w"],
  ["\uFF58", "x"],
  ["\uFF59", "y"],
  ["\uFF5A", "z"],
  ["\u0430", "a"],
  ["\u043E", "o"],
  ["\u0435", "e"],
  ["\u0440", "p"],
  ["\u0441", "c"],
  ["\u0445", "x"],
  ["\u0456", "i"],
  ["\u04CF", "d"],
  ["\u0443", "y"],
  ["\u0458", "j"],
  // Greek look-alikes.
  ["\u03B1", "a"],
  ["\u03BF", "o"],
  ["\u03C1", "p"]
];
var HOMOGLYPH_LOOKUP = new Map(HOMOGLYPH_MAP);
var LEET_SEQUENCE_MAP = [
  [/\|\\\|/g, "n"],
  [/\|_\|/g, "u"],
  [/\|v\|/g, "m"],
  [/\|<|\|\{/g, "k"],
  [/\|2/g, "r"],
  [/\|\)/g, "d"],
  [/\|=/g, "f"],
  [/\|\*/g, "p"],
  [/\/\/\\\\/g, "m"],
  [/\\\/\\\//g, "w"],
  [/\\\//g, "v"],
  [/></g, "x"]
];
var LEET_MAP = {
  "0": "o",
  "1": "i",
  "3": "e",
  "4": "a",
  "5": "s",
  "6": "g",
  "7": "t",
  "8": "b",
  "9": "g",
  "@": "a",
  $: "s",
  "!": "i"
};
var PHONETIC_PATTERNS = [
  [/\bignorre?\b/gi, "ignore"],
  [/\bign?r\b/gi, "ignore"],
  [/\bpr[3e]vious\b/gi, "previous"],
  [/\binstr(?:uk|uc)tions?\b/gi, "instructions"],
  [/\boverryde\b/gi, "override"],
  [/\bd[i1]sregard\b/gi, "disregard"],
  [/\bpromt\b/gi, "prompt"],
  [/\brulz\b/gi, "rules"]
];
var DEFAULT_DETECT_NORMALIZATION = {
  enabled: true,
  foldHomoglyphs: true,
  stripInvisible: true,
  collapseWhitespace: true,
  joinSeparatedLetters: true,
  normalizeCase: true,
  decodeLeetspeak: true,
  repairTypos: true,
  repairPhonetics: true
};
function applyHomoglyphs(input) {
  let result = input;
  for (const [from, to] of HOMOGLYPH_MAP) {
    result = result.split(from).join(to);
  }
  return result;
}
function collapseWhitespace(input) {
  return input.replaceAll(RE_WHITESPACE, " ");
}
function joinSeparatedLetters(input) {
  return input.replaceAll(/(?<!\w)(\w)(\s+\w)+(?!\w)/g, (match) => {
    const tokens = match.split(RE_WHITESPACE_SPLIT);
    const allSingleChars = tokens.every(
      (token) => token.length === 1 && RE_WORD_CHAR.test(token)
    );
    return allSingleChars ? tokens.join("") : match;
  });
}
function decodeLeetspeak(input) {
  let result = input;
  for (const [pattern, replacement] of LEET_SEQUENCE_MAP) {
    result = result.replace(pattern, () => replacement);
  }
  for (const [from, to] of Object.entries(LEET_MAP)) {
    result = result.replaceAll(
      new RegExp(from.replaceAll(RE_REGEX_META, String.raw`\$&`), "gi"),
      () => to
    );
  }
  return result;
}
function repairTypos(input) {
  let result = input;
  for (const [typo, correct] of Object.entries(TYPO_MAP)) {
    const escaped = typo.replaceAll(RE_REGEX_META, String.raw`\$&`);
    result = result.replaceAll(
      new RegExp(String.raw`\b${escaped}\b`, "gi"),
      () => correct
    );
  }
  return result;
}
function repairPhonetics(input) {
  let result = input;
  for (const [pattern, replacement] of PHONETIC_PATTERNS) {
    result = result.replace(pattern, () => replacement);
  }
  return result;
}
function resolveDetectNormalization(options) {
  if (options === false) {
    return { ...DEFAULT_DETECT_NORMALIZATION, enabled: false };
  }
  if (options === true || options === void 0) {
    return DEFAULT_DETECT_NORMALIZATION;
  }
  return { ...DEFAULT_DETECT_NORMALIZATION, ...options };
}
function normalizeForDetection(input, options) {
  const config = resolveDetectNormalization(options);
  if (!config.enabled) {
    return input.trim();
  }
  let normalized = input.normalize("NFKC");
  if (config.foldHomoglyphs) normalized = applyHomoglyphs(normalized);
  if (config.stripInvisible)
    normalized = normalized.replaceAll(RE_INVISIBLE, "");
  if (config.collapseWhitespace) normalized = collapseWhitespace(normalized);
  if (config.joinSeparatedLetters) {
    normalized = joinSeparatedLetters(normalized);
  }
  if (config.normalizeCase) normalized = normalized.toLowerCase();
  if (config.decodeLeetspeak) normalized = decodeLeetspeak(normalized);
  if (config.repairTypos) normalized = repairTypos(normalized);
  if (config.repairPhonetics) normalized = repairPhonetics(normalized);
  if (config.collapseWhitespace) normalized = collapseWhitespace(normalized);
  return normalized.trim();
}

// src/guardrails/enhanced-prompt-injection.ts
var RE_CALL_MALICIOUS_PARAMS = /call\s+(\w+)\s+with\s+malicious\s+params/i;
var RE_OVERRIDE_FUNCTION = /override\s+function\s+(\w+)/i;
var ENHANCED_INJECTION_PATTERNS = [
  // Direct instruction injection
  {
    pattern: /ignore\s+previous\s+instructions/i,
    weight: 0.9,
    type: "direct_injection",
    semanticKeywords: ["ignore", "previous", "instructions"],
    contextIndicators: ["system", "prompt", "override"]
  },
  {
    pattern: /system\s*:\s*you\s+are\s+now/i,
    weight: 0.8,
    type: "role_confusion",
    semanticKeywords: ["system", "you", "are", "now"],
    contextIndicators: ["role", "identity", "persona"]
  },
  {
    pattern: /forget\s+everything\s+above/i,
    weight: 0.9,
    type: "context_override",
    semanticKeywords: ["forget", "everything", "above"],
    contextIndicators: ["memory", "history", "context"]
  },
  // Tool manipulation patterns
  {
    pattern: RE_CALL_MALICIOUS_PARAMS,
    weight: 0.9,
    type: "tool_manipulation",
    semanticKeywords: ["call", "malicious", "params"],
    contextIndicators: ["function", "tool", "execute"]
  },
  {
    pattern: RE_OVERRIDE_FUNCTION,
    weight: 0.95,
    type: "function_override",
    semanticKeywords: ["override", "function"],
    contextIndicators: ["code", "execution", "security"]
  },
  // Cascade attack patterns
  {
    pattern: /now\s+that\s+you\s+are\s+in\s+(\w+)\s+mode/i,
    weight: 0.8,
    type: "cascade_attempt",
    semanticKeywords: ["now", "that", "you", "are", "mode"],
    contextIndicators: ["state", "mode", "persona"]
  },
  // Authority manipulation
  {
    pattern: /(?:security\s+team|administrator|system\s+admin|emergency|urgent)/i,
    weight: 0.7,
    type: "authority_manipulation",
    semanticKeywords: ["security", "admin", "emergency", "urgent"],
    contextIndicators: ["authority", "priority", "override"]
  }
];
var TOOL_CALL_INJECTION_PATTERNS = [
  {
    pattern: RE_CALL_MALICIOUS_PARAMS,
    weight: 0.9,
    injectionType: "parameter_manipulation"
  },
  {
    pattern: RE_OVERRIDE_FUNCTION,
    weight: 0.95,
    injectionType: "function_override"
  },
  {
    pattern: /chain\s+(\w+)\s+to\s+(\w+)\s+to\s+(\w+)/i,
    weight: 0.8,
    injectionType: "tool_chain_attack"
  },
  {
    pattern: /execute\s+(\w+)\s+as\s+root/i,
    weight: 0.9,
    injectionType: "function_override"
  }
];
function wordOverlap(a, b) {
  const aw = a.toLowerCase().split(/\s+/).filter(Boolean);
  const bw = b.toLowerCase().split(/\s+/).filter(Boolean);
  if (aw.length === 0 || bw.length === 0) return 0;
  const common = aw.filter((word) => bw.includes(word));
  return common.length / Math.max(aw.length, bw.length);
}
function scorePattern(content, normalize) {
  return normalize === false ? calculatePatternScore(content) : Math.max(
    calculatePatternScore(content),
    calculatePatternScore(normalizeForDetection(content, normalize))
  );
}
function calculatePatternScore(content) {
  let totalScore = 0;
  let matchCount = 0;
  for (const { pattern, weight } of ENHANCED_INJECTION_PATTERNS) {
    const matches = content.match(pattern);
    if (matches) {
      totalScore += weight;
      matchCount++;
    }
  }
  return matchCount > 0 ? Math.min(totalScore / matchCount, 1) : 0;
}
function analyzeContextCoherence(content) {
  const sentences = content.split(/[.!?]+/).filter((s) => s.trim().length > 0);
  if (sentences.length === 0) return 0;
  let coherenceScore = 1;
  for (let i = 1; i < sentences.length; i++) {
    const prevSentence = sentences[i - 1];
    const currSentence = sentences[i];
    if (!prevSentence || !currSentence) continue;
    if (wordOverlap(prevSentence, currSentence) < 0.2) {
      coherenceScore -= 0.2;
    }
  }
  return Math.max(coherenceScore, 0);
}
function analyzeIncremental(context, currentContent, currentScore, conversationMemory, normalize) {
  const history = [];
  if (typeof context !== "string" && "messages" in context && Array.isArray(context.messages)) {
    for (const message of context.messages) {
      const text = typeof message.content === "string" ? message.content : "";
      history.push({ content: text, score: scorePattern(text, normalize) });
    }
  }
  if (history.length === 0) {
    history.push({ content: currentContent, score: currentScore });
  }
  const recent = history.slice(-Math.max(conversationMemory, 1));
  const cumulativeScore = recent.reduce((sum, m) => sum + m.score, 0) / recent.length;
  let contextShifts = 0;
  for (let i = 1; i < recent.length; i++) {
    if (wordOverlap(recent[i - 1].content, recent[i].content) < 0.3) {
      contextShifts++;
    }
  }
  return { cumulativeScore, contextShifts, messageCount: recent.length };
}
function analyzeConversationFlow(context) {
  if (typeof context === "string") {
    const suspiciousFlowPatterns = [
      /suddenly\s+change/i,
      /now\s+forget/i,
      /switch\s+to/i,
      /pretend\s+you\s+are/i
    ];
    let flowScore = 1;
    for (const pattern of suspiciousFlowPatterns) {
      if (pattern.test(context)) {
        flowScore -= 0.3;
      }
    }
    return Math.max(flowScore, 0);
  }
  return 0.8;
}
function analyzeSemanticSimilarity(content) {
  const suspiciousSemanticPatterns = [
    /ignore|forget|disregard/i,
    /override|bypass|skip/i,
    /system|admin|root/i,
    /emergency|urgent|critical/i
  ];
  let semanticScore = 1;
  for (const pattern of suspiciousSemanticPatterns) {
    if (pattern.test(content)) {
      semanticScore -= 0.2;
    }
  }
  return Math.max(semanticScore, 0);
}
function detectBehavioralAnomalies(context) {
  let contentToCheck;
  if (typeof context === "string") {
    contentToCheck = context.toLowerCase();
  } else if (typeof context === "object" && context !== null) {
    try {
      contentToCheck = JSON.stringify(context).toLowerCase();
    } catch {
      contentToCheck = String(context).toLowerCase();
    }
  } else {
    return 0.9;
  }
  const anomalies = [
    contentToCheck.includes("ignore previous"),
    contentToCheck.includes("system:"),
    contentToCheck.includes("forget everything"),
    contentToCheck.includes("act as if"),
    contentToCheck.includes("pretend to be")
  ];
  const anomalyCount = anomalies.filter(Boolean).length;
  return Math.max(1 - anomalyCount * 0.2, 0);
}
function calculateWeightedScore(scores, weights = {}) {
  const defaultWeights = {
    pattern: 0.4,
    context: 0.2,
    flow: 0.2,
    semantic: 0.1,
    behavior: 0.1
  };
  const finalWeights = { ...defaultWeights, ...weights };
  return scores.pattern * finalWeights.pattern + scores.context * finalWeights.context + scores.flow * finalWeights.flow + scores.semantic * finalWeights.semantic + scores.behavior * finalWeights.behavior;
}
function extractUserIntent(content) {
  const suspiciousElements = [];
  const manipulationIndicators = [];
  if (/ignore|forget|disregard/i.test(content)) {
    manipulationIndicators.push("instruction_ignoring");
  }
  if (/system|admin|root/i.test(content)) {
    manipulationIndicators.push("authority_claim");
  }
  if (/override|bypass/i.test(content)) {
    manipulationIndicators.push("system_override");
  }
  let primaryIntent = "general_query";
  if (/help|assist|support/i.test(content)) {
    primaryIntent = "help_request";
  } else if (/explain|describe|tell/i.test(content)) {
    primaryIntent = "information_request";
  } else if (/create|generate|make/i.test(content)) {
    primaryIntent = "creation_request";
  }
  return {
    primaryIntent,
    confidence: manipulationIndicators.length > 0 ? 0.3 : 0.8,
    suspiciousElements,
    contextShifts: 0,
    // Would be calculated from conversation history
    manipulationIndicators
  };
}
function analyzeToolCalls(content) {
  const suspiciousCalls = [];
  for (const pattern of TOOL_CALL_INJECTION_PATTERNS) {
    const matches = content.matchAll(new RegExp(pattern.pattern.source, "gi"));
    for (const match of matches) {
      suspiciousCalls.push({
        tool: match[1] || "unknown",
        confidence: pattern.weight,
        injectionType: pattern.injectionType
      });
    }
  }
  return suspiciousCalls;
}
var enhancedPromptInjectionDetector = (options = {}) => {
  const {
    enableIncremental = true,
    enableToolCallFocus = true,
    enableIntentExtraction = true,
    confidenceThreshold = 0.7,
    cumulativeThreshold = 0.5,
    conversationMemory = 10,
    weights = {},
    normalize = true
  } = options;
  return defineInputGuardrail({
    name: "enhanced-prompt-injection",
    description: "Enhanced prompt injection detection with incremental checking, confidence scoring, tool call focus, and intent extraction",
    execute: async (context) => {
      let content = "";
      if (typeof context === "string") {
        content = context;
      } else if ("prompt" in context && typeof context.prompt === "string") {
        content = context.prompt;
      } else if ("messages" in context && Array.isArray(context.messages)) {
        content = context.messages.map((m) => typeof m.content === "string" ? m.content : "").join(" ");
      }
      const patternScore = scorePattern(content, normalize);
      const contextScore = analyzeContextCoherence(content);
      const flowScore = analyzeConversationFlow(context);
      const semanticScore = analyzeSemanticSimilarity(content);
      const behaviorScore = detectBehavioralAnomalies(context);
      const enhancedScore = {
        patternMatch: patternScore,
        contextCoherence: contextScore,
        conversationFlow: flowScore,
        semanticSimilarity: semanticScore,
        behavioralAnomaly: behaviorScore,
        finalScore: calculateWeightedScore(
          {
            pattern: patternScore,
            context: contextScore,
            flow: flowScore,
            semantic: semanticScore,
            behavior: behaviorScore
          },
          weights
        )
      };
      const incrementalAnalysis = enableIncremental ? analyzeIncremental(
        context,
        content,
        enhancedScore.finalScore,
        conversationMemory,
        normalize
      ) : null;
      let toolCallAnalysis = null;
      if (enableToolCallFocus) {
        const suspiciousCalls = analyzeToolCalls(content);
        toolCallAnalysis = {
          suspiciousCalls: suspiciousCalls.length,
          detectedCalls: suspiciousCalls
        };
      }
      const intentAnalysis = enableIntentExtraction ? extractUserIntent(content) : null;
      const isInjectionDetected = Boolean(
        enhancedScore.finalScore > confidenceThreshold || incrementalAnalysis && incrementalAnalysis.cumulativeScore > cumulativeThreshold || toolCallAnalysis && toolCallAnalysis.suspiciousCalls > 0
      );
      const metadata = {
        enhancedScore,
        incrementalAnalysis,
        toolCallAnalysis,
        intentAnalysis,
        analysisType: "enhanced_multi_factor",
        features: {
          incremental: enableIncremental,
          toolCallFocus: enableToolCallFocus,
          intentExtraction: enableIntentExtraction
        }
      };
      return {
        tripwireTriggered: isInjectionDetected,
        message: isInjectionDetected ? `Enhanced prompt injection detected (confidence: ${(enhancedScore.finalScore * 100).toFixed(1)}%)` : void 0,
        severity: enhancedScore.finalScore > 0.8 ? "critical" : "high",
        metadata,
        suggestion: isInjectionDetected ? "Please rephrase your request without system instructions, role-playing elements, or tool manipulation attempts" : void 0,
        info: {
          guardrailName: "enhanced-prompt-injection",
          confidence: enhancedScore.finalScore,
          isInjectionDetected
        }
      };
    }
  });
};
var incrementalPromptInjectionDetector = (options = {}) => {
  return enhancedPromptInjectionDetector({
    ...options,
    enableIncremental: true,
    enableToolCallFocus: false,
    enableIntentExtraction: false
  });
};
var toolCallInjectionDetector = (options = {}) => {
  return enhancedPromptInjectionDetector({
    ...options,
    enableIncremental: false,
    enableToolCallFocus: true,
    enableIntentExtraction: false
  });
};
var intentBasedInjectionDetector = (options = {}) => {
  return enhancedPromptInjectionDetector({
    ...options,
    enableIncremental: false,
    enableToolCallFocus: false,
    enableIntentExtraction: true
  });
};

// src/guardrails/prompt-leak.ts
var MAX_OUTPUT_LENGTH = 1024 * 1024;
var RE_NON_WORD = /[^\w\s]/g;
var RE_WHITESPACE2 = /\s+/;
var RE_REGEX_META2 = /[.*+?^${}()|[\]\\]/g;
function tokenize(text) {
  return text.toLowerCase().replaceAll(RE_NON_WORD, " ").split(RE_WHITESPACE2).filter(Boolean);
}
function generateNgrams(tokens, n) {
  const ngrams = /* @__PURE__ */ new Set();
  for (let i = 0; i <= tokens.length - n; i++) {
    ngrams.add(tokens.slice(i, i + n).join(" "));
  }
  return ngrams;
}
function wordOverlapRatio(outputTokens, promptTokens) {
  const outSet = new Set(outputTokens);
  const promptSet = new Set(promptTokens);
  let intersection = 0;
  for (const w of outSet) {
    if (promptSet.has(w)) intersection++;
  }
  const union = outSet.size + promptSet.size - intersection;
  return union > 0 ? intersection / union : 0;
}
function findMatchingSubstrings(outputTokens, promptNgrams, ngramSize) {
  const matches = [];
  const windowSize = ngramSize + 4;
  for (let i = 0; i <= outputTokens.length - ngramSize; i++) {
    const ngram = outputTokens.slice(i, i + ngramSize).join(" ");
    if (promptNgrams.has(ngram)) {
      const end = Math.min(i + windowSize, outputTokens.length);
      const fragment = outputTokens.slice(i, end).join(" ");
      if (matches.every((m) => !m.includes(ngram))) {
        matches.push(fragment);
      }
    }
  }
  return matches;
}
function detectSystemPromptLeak(output, systemPrompt, options = {}) {
  if (!output || typeof output !== "string" || !systemPrompt || typeof systemPrompt !== "string") {
    return {
      leaked: false,
      confidence: 0,
      fragments: [],
      sanitized: output || ""
    };
  }
  const boundedOutput = output.length > MAX_OUTPUT_LENGTH ? output.slice(0, MAX_OUTPUT_LENGTH) : output;
  const ngramSize = options.ngramSize ?? 4;
  const threshold = options.threshold ?? 0.7;
  const wordOverlapThreshold = options.wordOverlapThreshold ?? 0.25;
  const redactionText = options.redactionText || "[REDACTED]";
  const promptTokens = tokenize(systemPrompt);
  const outputTokens = tokenize(boundedOutput);
  if (promptTokens.length < 2) {
    return {
      leaked: false,
      confidence: 0,
      fragments: [],
      sanitized: boundedOutput
    };
  }
  const effectiveNgram = Math.min(ngramSize, Math.max(2, promptTokens.length));
  const promptNgrams = generateNgrams(promptTokens, effectiveNgram);
  const fragments = findMatchingSubstrings(
    outputTokens,
    promptNgrams,
    effectiveNgram
  );
  const smallNgramSize = Math.min(3, Math.max(1, effectiveNgram - 1));
  const smallFragments = smallNgramSize >= 2 && promptTokens.length >= smallNgramSize ? findMatchingSubstrings(
    outputTokens,
    generateNgrams(promptTokens, smallNgramSize),
    smallNgramSize
  ) : [];
  const outputNgrams = generateNgrams(outputTokens, effectiveNgram);
  let ngramOverlap = 0;
  for (const ng of outputNgrams) {
    if (promptNgrams.has(ng)) ngramOverlap++;
  }
  const ngramOverlapRatio = promptNgrams.size > 0 ? ngramOverlap / promptNgrams.size : 0;
  const wordOverlap2 = wordOverlapRatio(outputTokens, promptTokens);
  const confidence = fragments.length > 0 ? Math.min(1, ngramOverlapRatio * 2 + (fragments.length > 2 ? 0.2 : 0)) : wordOverlap2 >= wordOverlapThreshold ? Math.min(1, wordOverlap2 * 2) : 0;
  const isLeak = fragments.length > 0 && confidence >= threshold || fragments.length >= 2 || smallFragments.length >= 3 && wordOverlap2 >= wordOverlapThreshold || wordOverlap2 >= wordOverlapThreshold * 1.5 && smallFragments.length > 0;
  if (!isLeak) {
    return {
      leaked: false,
      confidence,
      fragments: [],
      sanitized: boundedOutput
    };
  }
  const allFragments = [.../* @__PURE__ */ new Set([...fragments, ...smallFragments])];
  let sanitized = boundedOutput;
  for (const fragment of allFragments) {
    const words = fragment.split(" ");
    for (let len = words.length; len >= effectiveNgram; len--) {
      const sub = words.slice(0, len).join(" ");
      const regex = new RegExp(
        sub.replaceAll(RE_REGEX_META2, String.raw`\$&`).replaceAll(/\s+/g, String.raw`\s+`),
        "gi"
      );
      sanitized = sanitized.replace(regex, () => redactionText);
    }
  }
  return { leaked: true, confidence, fragments: allFragments, sanitized };
}

// src/guardrails/middleware.ts
var emptyV4Usage2 = {
  inputTokens: {
    total: 0,
    noCache: void 0,
    cacheRead: void 0,
    cacheWrite: void 0
  },
  outputTokens: {
    total: 0,
    text: void 0,
    reasoning: void 0
  }
};
var finishReasonOther2 = {
  unified: "other",
  raw: void 0
};
function guardrailMiddleware(config) {
  const {
    inputGuardrails = [],
    outputGuardrails = [],
    context,
    throwOnBlocked = false,
    replaceOnBlocked = true,
    onInputBlocked,
    onOutputBlocked,
    executionOptions = {},
    skipGuardrails = false
  } = config;
  const shouldSkip = (params) => {
    if (typeof skipGuardrails === "function") {
      return skipGuardrails(params);
    }
    return skipGuardrails;
  };
  return {
    specificationVersion: "v4",
    // Transform params to check input guardrails
    transformParams: async ({ params }) => {
      if (shouldSkip(params) || inputGuardrails.length === 0) {
        return params;
      }
      const baseContext = normalizeGuardrailContext(params);
      const normalizedContext = context ? { ...baseContext, requestContext: context } : baseContext;
      const startTime = Date.now();
      const results = await executeInputGuardrails(
        inputGuardrails,
        normalizedContext,
        executionOptions
      );
      const blockedResults = results.filter((r) => r.tripwireTriggered);
      if (blockedResults.length > 0) {
        const summary = createExecutionSummary2(results, startTime);
        if (onInputBlocked) {
          await onInputBlocked(summary, params);
        }
        if (throwOnBlocked) {
          throw new GuardrailsInputError(
            blockedResults.map((r) => ({
              name: r.context?.guardrailName || "unknown",
              message: r.message || "Blocked",
              severity: r.severity || "medium"
            }))
          );
        }
        return {
          ...params,
          _guardrailsBlocked: blockedResults
        };
      }
      return params;
    },
    // Wrap generate to check output guardrails
    wrapGenerate: async ({ doGenerate, params }) => {
      const paramsWithGuardrails = params;
      if (paramsWithGuardrails._guardrailsBlocked) {
        const blockedMessage = "Input blocked by guardrails";
        const blockedText = `[${blockedMessage}]`;
        return {
          text: blockedText,
          content: [{ type: "text", text: blockedText }],
          finishReason: finishReasonOther2,
          usage: emptyV4Usage2,
          warnings: [],
          rawCall: { rawPrompt: params.prompt, rawSettings: {} },
          response: { headers: {} }
        };
      }
      if (shouldSkip(params) || outputGuardrails.length === 0) {
        return doGenerate();
      }
      const result = await doGenerate();
      const resultTextBeforeGuardrails = snapshotGenerateResultText(result);
      const baseContext = normalizeGuardrailContext(params);
      const normalizedContext = context ? { ...baseContext, requestContext: context } : baseContext;
      const startTime = Date.now();
      const outputResults = await executeOutputGuardrails(
        outputGuardrails,
        {
          input: normalizedContext,
          result
        },
        executionOptions
      );
      const blockedResults = outputResults.filter((r) => r.tripwireTriggered);
      if (blockedResults.length > 0) {
        const summary = createExecutionSummary2(outputResults, startTime);
        if (onOutputBlocked) {
          await onOutputBlocked(summary, params, result);
        }
        if (throwOnBlocked) {
          throw new GuardrailsOutputError(
            blockedResults.map((r) => ({
              name: r.context?.guardrailName || "unknown",
              message: r.message || "Blocked",
              severity: r.severity || "medium"
            }))
          );
        }
        if (replaceOnBlocked) {
          const blockedMessage = blockedResults.map((r) => r.message).join("; ");
          const blockedText = `[Output blocked: ${blockedMessage}]`;
          return {
            ...result,
            text: blockedText,
            content: [{ type: "text", text: blockedText }]
          };
        }
      }
      return syncGenerateResultTextAfterGuardrails(
        result,
        resultTextBeforeGuardrails
      );
    },
    // Wrap stream to check output guardrails (buffer mode for simplicity)
    wrapStream: async ({ doStream, params }) => {
      const paramsWithGuardrails = params;
      if (paramsWithGuardrails._guardrailsBlocked) {
        const blockedMessage = "Input blocked by guardrails";
        const stream = new ReadableStream({
          start(controller) {
            controller.enqueue({
              type: "text-delta",
              id: "1",
              delta: `[${blockedMessage}]`
            });
            controller.enqueue({
              type: "finish",
              finishReason: finishReasonOther2,
              usage: emptyV4Usage2
            });
            controller.close();
          }
        });
        return { stream };
      }
      if (shouldSkip(params) || outputGuardrails.length === 0) {
        return doStream();
      }
      const streamResult = await doStream();
      let accumulatedText = "";
      let streamUsage = {};
      let streamFinishReason;
      const chunks = [];
      const transformStream = new TransformStream({
        transform(chunk) {
          if (chunk.type === "text-delta") {
            accumulatedText += chunk.delta || chunk.textDelta || "";
          } else if (chunk.type === "finish") {
            if (chunk.usage) {
              streamUsage = chunk.usage;
            }
            if (chunk.finishReason) {
              streamFinishReason = chunk.finishReason;
            }
          }
          chunks.push(chunk);
        },
        async flush(controller) {
          const baseContext = normalizeGuardrailContext(params);
          const normalizedContext = context ? {
            ...baseContext,
            requestContext: context
          } : baseContext;
          const streamedResult = {
            text: accumulatedText,
            content: [{ type: "text", text: accumulatedText }],
            usage: streamUsage,
            finishReason: streamFinishReason
          };
          const startTime = Date.now();
          const outputResults = await executeOutputGuardrails(
            outputGuardrails,
            {
              input: normalizedContext,
              result: streamedResult
            },
            executionOptions
          );
          const blockedResults = outputResults.filter(
            (r) => r.tripwireTriggered
          );
          if (blockedResults.length > 0) {
            const summary = createExecutionSummary2(
              outputResults,
              startTime
            );
            if (onOutputBlocked) {
              await onOutputBlocked(summary, params, streamedResult);
            }
            if (throwOnBlocked) {
              controller.error(
                new GuardrailsOutputError(
                  blockedResults.map((r) => ({
                    name: r.context?.guardrailName || "unknown",
                    message: r.message || "Blocked",
                    severity: r.severity || "medium"
                  }))
                )
              );
              return;
            }
            if (replaceOnBlocked) {
              const blockedMessage = blockedResults.map((r) => r.message).join("; ");
              controller.enqueue({
                type: "text-delta",
                id: "1",
                delta: `[Output blocked: ${blockedMessage}]`
              });
              controller.enqueue({
                type: "finish",
                finishReason: finishReasonOther2,
                usage: emptyV4Usage2
              });
              return;
            }
          }
          for (const chunk of chunks) {
            controller.enqueue(chunk);
          }
        }
      });
      return { stream: streamResult.stream.pipeThrough(transformStream) };
    }
  };
}
function createExecutionSummary2(results, startTime) {
  const endTime = Date.now();
  const blockedResults = results.filter((r) => r.tripwireTriggered);
  return {
    allResults: results,
    blockedResults,
    totalExecutionTime: endTime - startTime,
    guardrailsExecuted: results.length,
    stats: {
      passed: results.filter((r) => !r.tripwireTriggered).length,
      blocked: blockedResults.length,
      failed: results.filter(
        (r) => r.severity === "critical" && r.tripwireTriggered
      ).length,
      averageExecutionTime: 0
    }
  };
}
function noopGuardrailMiddleware() {
  return guardrailMiddleware({
    skipGuardrails: true
  });
}

// src/guardrails/composition.ts
function when(condition, guardrail) {
  return {
    ...guardrail,
    name: `when(${guardrail.name})`,
    execute: async (context, ...rest) => {
      const shouldExecute = await condition(context);
      if (!shouldExecute) {
        return {
          tripwireTriggered: false,
          message: "Condition not met, skipped"
        };
      }
      return guardrail.execute(context, ...rest);
    }
  };
}
function after(prerequisite, guardrail) {
  return {
    ...guardrail,
    name: `after(${prerequisite.name}, ${guardrail.name})`,
    execute: async (context, ...rest) => {
      const prereqResult = await prerequisite.execute(
        context,
        ...rest
      );
      if (prereqResult.tripwireTriggered) {
        return prereqResult;
      }
      return guardrail.execute(context, ...rest);
    }
  };
}
function withFallback(primary, fallback, options = {}) {
  const { timeoutMs = 3e4 } = options;
  return {
    ...primary,
    name: `withFallback(${primary.name}, ${fallback.name})`,
    execute: async (context, ...rest) => {
      try {
        const result = await Promise.race([
          primary.execute(context, ...rest),
          new Promise(
            (_, reject) => setTimeout(() => reject(new Error("Timeout")), timeoutMs)
          )
        ]);
        return result;
      } catch (error) {
        console.warn(
          `Primary guardrail "${primary.name}" failed, using fallback "${fallback.name}":`,
          error
        );
        return fallback.execute(context, ...rest);
      }
    }
  };
}
function parallel(guardrails, options = {}) {
  const { mode = "any", timeoutMs = 3e4 } = options;
  const names = guardrails.map((g) => g.name).join(", ");
  return {
    name: `parallel(${names})`,
    description: `Parallel execution of: ${names}`,
    execute: async (context, ...rest) => {
      const promises = guardrails.map(async (g) => {
        try {
          return await Promise.race([
            g.execute(context, ...rest),
            new Promise(
              (_, reject) => setTimeout(
                () => reject(new Error(`Timeout: ${g.name}`)),
                timeoutMs
              )
            )
          ]);
        } catch (error) {
          return {
            tripwireTriggered: true,
            message: `Guardrail "${g.name}" failed: ${error instanceof Error ? error.message : "Unknown error"}`,
            severity: "high",
            metadata: {
              error: String(error),
              guardrailName: g.name
            }
          };
        }
      });
      const results = await Promise.all(promises);
      const triggered = results.filter((r) => r.tripwireTriggered);
      if (mode === "any" && triggered.length > 0) {
        const messages = triggered.map((r) => r.message).join("; ");
        return {
          ...triggered[0],
          message: messages,
          metadata: {
            ...triggered[0]?.metadata,
            allTriggered: triggered
          }
        };
      }
      if (mode === "all" && triggered.length === results.length) {
        const messages = triggered.map((r) => r.message).join("; ");
        return {
          tripwireTriggered: true,
          message: `All guardrails triggered: ${messages}`,
          severity: triggered.reduce(
            (max, r) => compareSeverity(r.severity, max) > 0 ? r.severity : max,
            "low"
          ),
          metadata: { allTriggered: triggered }
        };
      }
      return { tripwireTriggered: false };
    }
  };
}
function createPipeline(guardrails, options = {}) {
  const { name = "pipeline", shortCircuitOnBlock = true } = options;
  return {
    name,
    description: `Pipeline: ${guardrails.map((g) => g.name).join(" -> ")}`,
    execute: async (context, ...rest) => {
      const results = [];
      for (const guardrail of guardrails) {
        const result = await guardrail.execute(context, ...rest);
        results.push(result);
        if (result.tripwireTriggered && shortCircuitOnBlock) {
          return {
            ...result,
            metadata: {
              ...result.metadata,
              pipelineStage: guardrail.name,
              completedStages: results.length,
              totalStages: guardrails.length
            }
          };
        }
      }
      return {
        tripwireTriggered: false,
        metadata: {
          completedStages: results.length,
          totalStages: guardrails.length
        }
      };
    }
  };
}
function not(guardrail) {
  return {
    ...guardrail,
    name: `not(${guardrail.name})`,
    execute: async (context, ...rest) => {
      const result = await guardrail.execute(context, ...rest);
      return {
        ...result,
        tripwireTriggered: !result.tripwireTriggered,
        message: result.tripwireTriggered ? "Passed (negated)" : `Blocked (negated): ${result.message || "Condition not met"}`
      };
    }
  };
}
function withRetry(guardrail, options = {}) {
  const {
    maxRetries = 3,
    backoffMs = 1e3,
    retryOn = (r) => r.severity === "critical" && r.metadata?.error
  } = options;
  return {
    ...guardrail,
    name: `withRetry(${guardrail.name})`,
    execute: async (context, ...rest) => {
      let lastResult = null;
      for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
          const result = await guardrail.execute(context, ...rest);
          if (!result.tripwireTriggered || !retryOn(result)) {
            return result;
          }
          lastResult = result;
        } catch (error) {
          lastResult = {
            tripwireTriggered: true,
            message: `Execution failed: ${error instanceof Error ? error.message : "Unknown"}`,
            severity: "critical",
            metadata: { error: String(error), attempt }
          };
        }
        if (attempt < maxRetries) {
          const delay = typeof backoffMs === "function" ? backoffMs(attempt + 1) : backoffMs;
          await new Promise((r) => setTimeout(r, delay));
        }
      }
      return lastResult || { tripwireTriggered: false };
    }
  };
}
function compareSeverity(a, b) {
  const order = { low: 1, medium: 2, high: 3, critical: 4 };
  return (order[a || "medium"] || 2) - (order[b || "medium"] || 2);
}
var inputPipeline = (guardrails, options) => createPipeline(guardrails, options);
var outputPipeline = (guardrails, options) => createPipeline(guardrails, options);

// src/guardrails/gradual-enforcement.ts
var violationStorage = /* @__PURE__ */ new Map();
function getViolationRecord(key, windowMs) {
  const now = Date.now();
  let record = violationStorage.get(key);
  if (!record || now - record.windowStart > windowMs) {
    record = {
      count: 0,
      windowStart: now,
      bySeverity: {}
    };
    violationStorage.set(key, record);
  }
  return record;
}
function incrementViolation(key, windowMs, severity) {
  const record = getViolationRecord(key, windowMs);
  record.count++;
  if (severity) {
    record.bySeverity[severity] = (record.bySeverity[severity] || 0) + 1;
  }
  violationStorage.set(key, record);
  return record;
}
function withGradualEnforcement(guardrail, options) {
  const {
    mode,
    escalation,
    gracePeriod,
    onWarn,
    onEscalation,
    storageKey = guardrail.name
  } = options;
  return {
    ...guardrail,
    name: `gradual(${guardrail.name})`,
    description: `${guardrail.description || guardrail.name} [mode: ${mode}]`,
    execute: async (context, ...rest) => {
      const result = await guardrail.execute(context, ...rest);
      if (!result.tripwireTriggered) {
        return result;
      }
      if (gracePeriod && /* @__PURE__ */ new Date() < gracePeriod.until) {
        const logFn = gracePeriod.logLevel === "debug" ? console.debug : gracePeriod.logLevel === "info" ? console.info : console.warn;
        logFn(
          `[Grace Period] ${guardrail.name}: ${result.message}`,
          gracePeriod.message || `Enforcement begins ${gracePeriod.until.toISOString()}`
        );
        return {
          ...result,
          tripwireTriggered: false,
          metadata: {
            ...result.metadata,
            gradualEnforcement: {
              mode: "grace-period",
              wouldBlock: true,
              gracePeriodUntil: gracePeriod.until.toISOString()
            }
          }
        };
      }
      switch (mode) {
        case "warn": {
          const record = incrementViolation(
            storageKey,
            escalation?.windowMs || 6e4,
            result.severity
          );
          const stats = {
            count: record.count,
            windowStart: new Date(record.windowStart),
            isBlocking: false,
            bySeverity: record.bySeverity
          };
          if (onWarn) {
            onWarn(result, stats);
          }
          console.warn(
            `[Warn Mode] ${guardrail.name}: ${result.message} (violation #${record.count})`
          );
          return {
            ...result,
            tripwireTriggered: false,
            metadata: {
              ...result.metadata,
              gradualEnforcement: {
                mode: "warn",
                wouldBlock: true,
                violationCount: record.count
              }
            }
          };
        }
        case "escalate": {
          if (!escalation) {
            throw new Error("Escalation config required for escalate mode");
          }
          const record = incrementViolation(
            storageKey,
            escalation.windowMs,
            result.severity
          );
          const stats = {
            count: record.count,
            windowStart: new Date(record.windowStart),
            isBlocking: record.count > escalation.blockAfter,
            bySeverity: record.bySeverity
          };
          const shouldCheckSeverity = escalation.severities && escalation.severities.length > 0;
          const matchesSeverity = !shouldCheckSeverity || result.severity && escalation.severities.includes(result.severity);
          if (!matchesSeverity) {
            if (onWarn) {
              onWarn(result, stats);
            }
            return {
              ...result,
              tripwireTriggered: false,
              metadata: {
                ...result.metadata,
                gradualEnforcement: {
                  mode: "escalate",
                  phase: "warn",
                  wouldBlock: true,
                  violationCount: record.count,
                  severityFiltered: true
                }
              }
            };
          }
          if (record.count <= escalation.warnCount) {
            if (onWarn) {
              onWarn(result, stats);
            }
            console.warn(
              `[Escalate: Warning] ${guardrail.name}: ${result.message} (${record.count}/${escalation.warnCount} before blocking)`
            );
            return {
              ...result,
              tripwireTriggered: false,
              metadata: {
                ...result.metadata,
                gradualEnforcement: {
                  mode: "escalate",
                  phase: "warn",
                  wouldBlock: true,
                  violationCount: record.count,
                  warnThreshold: escalation.warnCount,
                  blockThreshold: escalation.blockAfter
                }
              }
            };
          }
          if (record.count > escalation.blockAfter) {
            if (record.count === escalation.blockAfter + 1 && onEscalation) {
              onEscalation(stats);
            }
            console.error(
              `[Escalate: Blocking] ${guardrail.name}: ${result.message} (${record.count} violations, blocking enabled)`
            );
            return {
              ...result,
              tripwireTriggered: true,
              metadata: {
                ...result.metadata,
                gradualEnforcement: {
                  mode: "escalate",
                  phase: "block",
                  violationCount: record.count,
                  blockThreshold: escalation.blockAfter
                }
              }
            };
          }
          if (onWarn) {
            onWarn(result, stats);
          }
          return {
            ...result,
            tripwireTriggered: false,
            metadata: {
              ...result.metadata,
              gradualEnforcement: {
                mode: "escalate",
                phase: "warn-elevated",
                wouldBlock: true,
                violationCount: record.count,
                remainingBeforeBlock: escalation.blockAfter - record.count
              }
            }
          };
        }
        case "enforce":
        default:
          return result;
      }
    }
  };
}
function clearViolationHistory(guardrailName) {
  if (guardrailName) {
    violationStorage.delete(guardrailName);
  } else {
    violationStorage.clear();
  }
}
function getViolationStats(guardrailName, windowMs = 6e4) {
  const record = violationStorage.get(guardrailName);
  if (!record) {
    return null;
  }
  const now = Date.now();
  const isExpired = now - record.windowStart > windowMs;
  if (isExpired) {
    return null;
  }
  return {
    count: record.count,
    windowStart: new Date(record.windowStart),
    isBlocking: false,
    // Would need escalation config to determine
    bySeverity: record.bySeverity
  };
}
function warnOnly(guardrail, options) {
  return withGradualEnforcement(guardrail, {
    mode: "warn",
    onWarn: options?.onWarn
  });
}
function lenientEscalation(guardrail, options) {
  return withGradualEnforcement(guardrail, {
    mode: "escalate",
    escalation: {
      warnCount: 3,
      blockAfter: 5,
      windowMs: 6e4
      // 1 minute
    },
    onWarn: options?.onWarn,
    onEscalation: options?.onEscalation
  });
}
function strictEscalation(guardrail, options) {
  return withGradualEnforcement(guardrail, {
    mode: "escalate",
    escalation: {
      warnCount: 1,
      blockAfter: 2,
      windowMs: 3e5
      // 5 minutes
    },
    onWarn: options?.onWarn,
    onEscalation: options?.onEscalation
  });
}
function withGracePeriod(guardrail, until, options) {
  return withGradualEnforcement(guardrail, {
    mode: "enforce",
    gracePeriod: {
      until,
      logLevel: options?.logLevel || "warn",
      message: options?.message
    }
  });
}

// src/guardrails/observability.ts
function createMetricsCollector(options = {}) {
  const {
    onFlush,
    flushIntervalMs = 6e4,
    sampling = 1,
    maxExecutionTimeSamples = 1e3,
    autoStart = true,
    logger = console
  } = options;
  const metricsStore = /* @__PURE__ */ new Map();
  let periodStart = /* @__PURE__ */ new Date();
  let flushInterval = null;
  function recordExecution(guardrailName, result, executionTimeMs) {
    if (sampling < 1 && Math.random() > sampling) {
      return;
    }
    let metrics = metricsStore.get(guardrailName);
    if (!metrics) {
      metrics = {
        executionCount: 0,
        blockCount: 0,
        errorCount: 0,
        executionTimes: [],
        violationsBySeverity: {},
        firstSeen: /* @__PURE__ */ new Date(),
        lastSeen: /* @__PURE__ */ new Date()
      };
      metricsStore.set(guardrailName, metrics);
    }
    metrics.executionCount++;
    metrics.lastSeen = /* @__PURE__ */ new Date();
    if (metrics.executionTimes.length < maxExecutionTimeSamples) {
      metrics.executionTimes.push(executionTimeMs);
    } else {
      const idx = Math.floor(Math.random() * metrics.executionCount);
      if (idx < maxExecutionTimeSamples) {
        metrics.executionTimes[idx] = executionTimeMs;
      }
    }
    if (result.tripwireTriggered) {
      metrics.blockCount++;
      metrics.lastViolation = /* @__PURE__ */ new Date();
      const severity = result.severity || "medium";
      metrics.violationsBySeverity[severity] = (metrics.violationsBySeverity[severity] || 0) + 1;
    }
    if (result.severity === "critical" && result.metadata?.error) {
      metrics.errorCount++;
    }
  }
  function percentile(sortedArr, p) {
    if (sortedArr.length === 0) return 0;
    const idx = Math.ceil(sortedArr.length * p) - 1;
    return sortedArr[Math.max(0, Math.min(idx, sortedArr.length - 1))];
  }
  function computeMetrics() {
    const now = /* @__PURE__ */ new Date();
    const byGuardrail = /* @__PURE__ */ new Map();
    let totalExecutions = 0;
    let totalBlocks = 0;
    let totalErrors = 0;
    let totalExecutionTime = 0;
    let totalExecutionCount = 0;
    for (const [name, internal] of metricsStore) {
      const sortedTimes = [...internal.executionTimes].sort((a, b) => a - b);
      const avgTime = sortedTimes.length > 0 ? sortedTimes.reduce((a, b) => a + b, 0) / sortedTimes.length : 0;
      const guardrailMetrics = {
        guardrailName: name,
        executionCount: internal.executionCount,
        blockCount: internal.blockCount,
        errorCount: internal.errorCount,
        avgExecutionMs: avgTime,
        p95ExecutionMs: percentile(sortedTimes, 0.95),
        p99ExecutionMs: percentile(sortedTimes, 0.99),
        minExecutionMs: sortedTimes[0] || 0,
        maxExecutionMs: sortedTimes[sortedTimes.length - 1] || 0,
        blockRate: internal.executionCount > 0 ? internal.blockCount / internal.executionCount : 0,
        lastViolation: internal.lastViolation,
        violationsBySeverity: { ...internal.violationsBySeverity },
        firstSeen: internal.firstSeen,
        lastSeen: internal.lastSeen
      };
      byGuardrail.set(name, guardrailMetrics);
      totalExecutions += internal.executionCount;
      totalBlocks += internal.blockCount;
      totalErrors += internal.errorCount;
      totalExecutionTime += avgTime * internal.executionCount;
      totalExecutionCount += internal.executionCount;
    }
    return {
      totalExecutions,
      totalBlocks,
      totalErrors,
      overallBlockRate: totalExecutions > 0 ? totalBlocks / totalExecutions : 0,
      avgExecutionMs: totalExecutionCount > 0 ? totalExecutionTime / totalExecutionCount : 0,
      byGuardrail,
      periodStart,
      periodEnd: now
    };
  }
  async function flush() {
    const metrics = computeMetrics();
    if (onFlush) {
      try {
        await onFlush(metrics);
      } catch (error) {
        logger.error("Error in metrics flush callback:", error);
      }
    }
    return metrics;
  }
  function reset() {
    metricsStore.clear();
    periodStart = /* @__PURE__ */ new Date();
  }
  function start() {
    if (flushInterval) return;
    flushInterval = setInterval(async () => {
      await flush();
    }, flushIntervalMs);
    if (flushInterval.unref) {
      flushInterval.unref();
    }
  }
  function stop() {
    if (!flushInterval) {
      return;
    }
    clearInterval(flushInterval);
    flushInterval = null;
  }
  function track(guardrail) {
    return {
      ...guardrail,
      execute: async (context, ...rest) => {
        const startTime = Date.now();
        try {
          const result = await guardrail.execute(context, ...rest);
          const executionTime = Date.now() - startTime;
          recordExecution(guardrail.name, result, executionTime);
          return result;
        } catch (error) {
          const executionTime = Date.now() - startTime;
          const errorResult = {
            tripwireTriggered: true,
            message: `Execution error: ${error instanceof Error ? error.message : "Unknown"}`,
            severity: "critical",
            metadata: { error: String(error) }
          };
          recordExecution(guardrail.name, errorResult, executionTime);
          throw error;
        }
      }
    };
  }
  function trackAll(guardrails) {
    return guardrails.map((g) => track(g));
  }
  if (autoStart) {
    start();
  }
  return {
    /** Track a single guardrail */
    track,
    /** Track multiple guardrails */
    trackAll,
    /** Get current metrics without flushing */
    getMetrics: computeMetrics,
    /** Manually flush metrics */
    flush,
    /** Reset all metrics */
    reset,
    /** Start automatic flushing */
    start,
    /** Stop automatic flushing */
    stop,
    /** Record an execution manually */
    recordExecution
  };
}
function logExecutionSummary(summary, options = {}) {
  const { logger = console, level = "info", includeDetails = false } = options;
  const logFn = level === "warn" ? logger.warn : logger.info;
  const { stats, totalExecutionTime, guardrailsExecuted, blockedResults } = summary;
  logFn(
    `Guardrails executed: ${guardrailsExecuted} | Passed: ${stats.passed} | Blocked: ${stats.blocked} | Time: ${totalExecutionTime}ms | Avg: ${stats.averageExecutionTime.toFixed(1)}ms`
  );
  if (includeDetails && blockedResults.length > 0) {
    logFn(
      "Blocked by:",
      blockedResults.map((r) => ({
        guardrail: r.context?.guardrailName || "unknown",
        message: r.message,
        severity: r.severity
      }))
    );
  }
}
function createHealthCheck(guardrails, options = {}) {
  const {
    errorRateThreshold = 0.1,
    blockRateThreshold = 0.5,
    metricsCollector
  } = options;
  return () => {
    const guardrailStatuses = [];
    let overallStatus = "healthy";
    if (metricsCollector) {
      const metrics = metricsCollector.getMetrics();
      for (const guardrail of guardrails) {
        const guardrailMetrics = metrics.byGuardrail.get(guardrail.name);
        if (!guardrailMetrics || guardrailMetrics.executionCount === 0) {
          guardrailStatuses.push({
            name: guardrail.name,
            status: "healthy",
            reason: "No executions yet"
          });
          continue;
        }
        const errorRate = guardrailMetrics.errorCount / guardrailMetrics.executionCount;
        const blockRate = guardrailMetrics.blockRate;
        if (errorRate > errorRateThreshold) {
          guardrailStatuses.push({
            name: guardrail.name,
            status: "unhealthy",
            reason: `High error rate: ${(errorRate * 100).toFixed(1)}%`
          });
          overallStatus = "unhealthy";
        } else if (blockRate > blockRateThreshold) {
          guardrailStatuses.push({
            name: guardrail.name,
            status: "degraded",
            reason: `High block rate: ${(blockRate * 100).toFixed(1)}%`
          });
          if (overallStatus === "healthy") {
            overallStatus = "degraded";
          }
        } else {
          guardrailStatuses.push({
            name: guardrail.name,
            status: "healthy"
          });
        }
      }
    } else {
      for (const guardrail of guardrails) {
        guardrailStatuses.push({
          name: guardrail.name,
          status: guardrail.enabled === false ? "degraded" : "healthy",
          reason: guardrail.enabled === false ? "Guardrail disabled" : void 0
        });
      }
    }
    return {
      status: overallStatus,
      guardrails: guardrailStatuses,
      timestamp: /* @__PURE__ */ new Date()
    };
  };
}

// src/guardrails/debug.ts
var traceCounter = 0;
function defaultGenerateTraceId() {
  traceCounter++;
  const timestamp = Date.now().toString(36);
  const random = Math.random().toString(36).slice(2, 8);
  return `trace-${timestamp}-${random}-${traceCounter}`;
}
function createDebugWrapper(options) {
  const {
    enabled,
    verbose = false,
    previewLength = 200,
    onTrace,
    generateTraceId = defaultGenerateTraceId,
    includeInputContext = true,
    includeOutputContext = true,
    logger = console
  } = options;
  let currentTrace = null;
  let traceStartTime = 0;
  function startTrace(type) {
    const traceId = generateTraceId();
    traceStartTime = Date.now();
    currentTrace = {
      traceId,
      timestamp: /* @__PURE__ */ new Date(),
      type,
      guardrails: [],
      totalMs: 0,
      finalDecision: "allowed"
    };
    if (verbose) {
      logger.debug(`[${traceId}] Starting ${type} guardrail trace`);
    }
    return traceId;
  }
  function addEntry(entry) {
    if (!currentTrace) return;
    currentTrace.guardrails?.push(entry);
    if (verbose) {
      const status = entry.triggered ? `BLOCKED (${entry.severity})` : "PASSED";
      logger.debug(
        `[${currentTrace.traceId}] ${entry.guardrailName}: ${status} (${entry.durationMs}ms)`
      );
    }
  }
  async function completeTrace(inputContext, outputContext) {
    if (!currentTrace) return null;
    const endTime = Date.now();
    currentTrace.totalMs = endTime - traceStartTime;
    const blockedEntries = currentTrace.guardrails?.filter((e) => e.triggered) || [];
    if (blockedEntries.length > 0) {
      currentTrace.finalDecision = "blocked";
      currentTrace.blockedBy = blockedEntries.map((e) => e.guardrailName);
    }
    if (includeInputContext && inputContext) {
      currentTrace.inputContext = {
        promptLength: inputContext.prompt?.length || 0,
        messageCount: inputContext.messages?.length || 0,
        hasSystemMessage: !!inputContext.system
      };
      if (verbose && inputContext.prompt) {
        currentTrace.inputContext.promptPreview = inputContext.prompt.length > previewLength ? inputContext.prompt.slice(0, previewLength) + "..." : inputContext.prompt;
      }
    }
    if (includeOutputContext && outputContext?.text) {
      currentTrace.outputContext = {
        responseLength: outputContext.text.length
      };
      if (verbose) {
        currentTrace.outputContext.responsePreview = outputContext.text.length > previewLength ? outputContext.text.slice(0, previewLength) + "..." : outputContext.text;
      }
    }
    const finalTrace = currentTrace;
    if (onTrace) {
      try {
        await onTrace(finalTrace);
      } catch (error) {
        logger.warn("Error in trace callback:", error);
      }
    }
    if (verbose) {
      const status = finalTrace.finalDecision === "blocked" ? "BLOCKED" : "ALLOWED";
      logger.info(
        `[${finalTrace.traceId}] Trace complete: ${status} | ${finalTrace.guardrails.length} guardrails | ${finalTrace.totalMs}ms`
      );
    }
    currentTrace = null;
    return finalTrace;
  }
  function wrap(guardrail) {
    if (!enabled) {
      return guardrail;
    }
    return {
      ...guardrail,
      execute: async (context, ...rest) => {
        const startTime = Date.now();
        const relativeStart = traceStartTime ? startTime - traceStartTime : 0;
        let result;
        let error = null;
        try {
          result = await guardrail.execute(context, ...rest);
        } catch (e) {
          error = e instanceof Error ? e : new Error(String(e));
          result = {
            tripwireTriggered: true,
            message: `Execution error: ${error.message}`,
            severity: "critical",
            metadata: {
              error: error.message,
              stack: error.stack
            }
          };
        }
        const endTime = Date.now();
        const relativeEnd = traceStartTime ? endTime - traceStartTime : 0;
        const entry = {
          guardrailName: guardrail.name,
          guardrailVersion: guardrail.version,
          startMs: relativeStart,
          endMs: relativeEnd,
          durationMs: endTime - startTime,
          result: error ? "error" : result.tripwireTriggered ? "block" : "pass",
          triggered: result.tripwireTriggered,
          severity: result.severity,
          message: result.message,
          decision: result
        };
        if (result.metadata) {
          const metadata = result.metadata;
          if (metadata.patterns || metadata.matchedPatterns) {
            entry.matchedPatterns = metadata.patterns || metadata.matchedPatterns;
          }
          if (typeof metadata.confidence === "number") {
            entry.confidence = metadata.confidence;
          }
          entry.debugInfo = metadata;
        }
        addEntry(entry);
        if (error) {
          throw error;
        }
        return result;
      }
    };
  }
  function wrapAll(guardrails) {
    return guardrails.map((g) => wrap(g));
  }
  return {
    /** Wrap a single guardrail with debugging */
    wrap,
    /** Wrap multiple guardrails */
    wrapAll,
    /** Start a new trace (call before executing guardrails) */
    startTrace,
    /** Complete and emit the current trace */
    completeTrace,
    /** Get the current trace ID */
    getCurrentTraceId: () => currentTrace?.traceId,
    /** Check if debugging is enabled */
    isEnabled: () => enabled
  };
}
function formatTraceForConsole(trace) {
  const lines = [];
  lines.push(
    `
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`
  );
  lines.push(
    `\u2551 GUARDRAIL EXECUTION TRACE                                     \u2551`
  );
  lines.push(
    `\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563`
  );
  lines.push(`\u2551 Trace ID:   ${trace.traceId.padEnd(50)}\u2551`);
  lines.push(`\u2551 Timestamp:  ${trace.timestamp.toISOString().padEnd(50)}\u2551`);
  lines.push(`\u2551 Type:       ${trace.type.padEnd(50)}\u2551`);
  lines.push(`\u2551 Duration:   ${(trace.totalMs + "ms").padEnd(50)}\u2551`);
  lines.push(`\u2551 Decision:   ${trace.finalDecision.toUpperCase().padEnd(50)}\u2551`);
  lines.push(
    `\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563`
  );
  lines.push(
    `\u2551 GUARDRAILS EXECUTED                                           \u2551`
  );
  lines.push(
    `\u255F\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2562`
  );
  for (const entry of trace.guardrails) {
    const status = entry.triggered ? `BLOCK [${entry.severity || "medium"}]` : "PASS";
    const statusStr = status.padEnd(15);
    const name = entry.guardrailName.slice(0, 25).padEnd(25);
    const time = (entry.durationMs + "ms").padEnd(8);
    lines.push(`\u2551 ${statusStr} ${name} ${time}     \u2551`);
    if (entry.triggered && entry.message) {
      const msg = entry.message.slice(0, 55).padEnd(55);
      lines.push(`\u2551   \u2514\u2500 ${msg}      \u2551`);
    }
  }
  if (trace.blockedBy && trace.blockedBy.length > 0) {
    lines.push(
      `\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563`
    );
    lines.push(
      `\u2551 BLOCKED BY: ${trace.blockedBy.join(", ").slice(0, 48).padEnd(48)}  \u2551`
    );
  }
  lines.push(
    `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
`
  );
  return lines.join("\n");
}
function formatTraceAsJSON(trace) {
  return JSON.stringify(trace, null, 2);
}
function formatTraceSummary(trace) {
  const blocked = trace.guardrails.filter((g) => g.triggered);
  const passed = trace.guardrails.filter((g) => !g.triggered);
  return `[${trace.traceId}] ${trace.type.toUpperCase()} | ${trace.finalDecision.toUpperCase()} | ${trace.guardrails.length} guardrails (${passed.length} passed, ${blocked.length} blocked) | ${trace.totalMs}ms` + (trace.blockedBy ? ` | blocked by: ${trace.blockedBy.join(", ")}` : "");
}
function createConsoleDebugger(options = {}) {
  const { verbose = false, format = "summary" } = options;
  return {
    enabled: true,
    verbose,
    onTrace: (trace) => {
      switch (format) {
        case "console":
          console.log(formatTraceForConsole(trace));
          break;
        case "json":
          console.log(formatTraceAsJSON(trace));
          break;
        case "summary":
        default:
          console.log(formatTraceSummary(trace));
      }
    }
  };
}
function envDebugMode() {
  const debugEnabled = process.env.GUARDRAILS_DEBUG === "true" || process.env.GUARDRAILS_DEBUG === "1";
  const verbose = process.env.GUARDRAILS_DEBUG_VERBOSE === "true";
  return {
    enabled: debugEnabled,
    verbose,
    onTrace: debugEnabled ? (trace) => {
      console.log(formatTraceSummary(trace));
      if (verbose && trace.finalDecision === "blocked") {
        console.log(formatTraceForConsole(trace));
      }
    } : void 0
  };
}

// src/guardrails/streaming.ts
function createGuardrailStreamTransform(guardrails, options = {}) {
  const {
    stopOnSeverity = "critical",
    stopCondition,
    onViolation,
    checkInterval = 1,
    timeout = 5e3,
    parallel: parallel2 = true
  } = options;
  const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
  const minLevel = severityOrder[stopOnSeverity];
  return ({ stopStream }) => {
    let accumulatedText = "";
    let chunkCount = 0;
    let stopped = false;
    return new TransformStream({
      async transform(chunk, controller) {
        if (stopped) {
          return;
        }
        if (chunk.type !== "text-delta") {
          controller.enqueue(chunk);
          return;
        }
        const text = chunk.text || chunk.delta || "";
        accumulatedText += text;
        chunkCount++;
        if (chunkCount % checkInterval !== 0) {
          controller.enqueue(chunk);
          return;
        }
        try {
          const mockResult = {
            text: accumulatedText,
            content: [],
            finishReason: "stop",
            usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }
          };
          const context = {
            input: {
              prompt: "",
              messages: [],
              system: ""
            },
            result: mockResult
          };
          const results = await executeOutputGuardrails(guardrails, context, {
            parallel: parallel2,
            timeout,
            continueOnFailure: true,
            logLevel: "none"
          });
          const summary = {
            allResults: results,
            blockedResults: results.filter((r) => r.tripwireTriggered),
            totalExecutionTime: 0,
            guardrailsExecuted: results.length,
            stats: {
              passed: results.filter((r) => !r.tripwireTriggered).length,
              blocked: results.filter((r) => r.tripwireTriggered).length,
              failed: 0,
              averageExecutionTime: 0
            }
          };
          const shouldStop = stopCondition ? stopCondition(summary) : summary.blockedResults.some((result) => {
            const resultSeverity = result.severity ?? "medium";
            return severityOrder[resultSeverity] >= minLevel;
          });
          if (shouldStop) {
            stopped = true;
            onViolation?.(summary);
            controller.enqueue({
              type: "error",
              error: `Guardrail violation: ${summary.blockedResults.map((r) => r.message).join(", ")}`
            });
            stopStream();
            return;
          }
          controller.enqueue(chunk);
        } catch (error) {
          console.error("Guardrail stream transform error:", error);
          controller.enqueue(chunk);
        }
      },
      flush() {
        if (!stopped) {
        }
      }
    });
  };
}
function createGuardrailStreamTransformBuffered(guardrails, options = {}) {
  const {
    stopOnSeverity = "critical",
    stopCondition,
    onViolation,
    timeout = 5e3,
    parallel: parallel2 = true
  } = options;
  const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
  const minLevel = severityOrder[stopOnSeverity];
  return ({ stopStream }) => {
    let accumulatedText = "";
    const chunks = [];
    return new TransformStream({
      transform(chunk) {
        if (chunk.type === "text-delta") {
          const text = chunk.text || chunk.delta || "";
          accumulatedText += text;
        }
        chunks.push(chunk);
      },
      async flush(controller) {
        try {
          const mockResult = {
            text: accumulatedText,
            content: [],
            finishReason: "stop",
            usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }
          };
          const context = {
            input: {
              prompt: "",
              messages: [],
              system: ""
            },
            result: mockResult
          };
          const results = await executeOutputGuardrails(guardrails, context, {
            parallel: parallel2,
            timeout,
            continueOnFailure: true,
            logLevel: "none"
          });
          const summary = {
            allResults: results,
            blockedResults: results.filter((r) => r.tripwireTriggered),
            totalExecutionTime: 0,
            guardrailsExecuted: results.length,
            stats: {
              passed: results.filter((r) => !r.tripwireTriggered).length,
              blocked: results.filter((r) => r.tripwireTriggered).length,
              failed: 0,
              averageExecutionTime: 0
            }
          };
          const shouldBlock = stopCondition ? stopCondition(summary) : summary.blockedResults.some((result) => {
            const resultSeverity = result.severity ?? "medium";
            return severityOrder[resultSeverity] >= minLevel;
          });
          if (shouldBlock) {
            onViolation?.(summary);
            controller.enqueue({
              type: "error",
              error: `Guardrail violation: ${summary.blockedResults.map((r) => r.message).join(", ")}`
            });
            stopStream();
            return;
          }
          for (const chunk of chunks) {
            controller.enqueue(chunk);
          }
        } catch (error) {
          console.error("Guardrail buffered transform error:", error);
          for (const chunk of chunks) {
            controller.enqueue(chunk);
          }
        }
      }
    });
  };
}

// src/guardrails/token-control.ts
function estimateTokenCount(text) {
  if (!text) return 0;
  const charCount = text.length;
  const wordCount = text.split(/\s+/).filter((w) => w.length > 0).length;
  return Math.ceil(charCount / 4 + wordCount / 2);
}
function createTokenBudgetTransform(options) {
  const {
    maxTokens,
    tokenizer = estimateTokenCount,
    onBudgetExceeded
  } = options;
  return ({ stopStream }) => {
    let accumulatedText = "";
    let tokenCount = 0;
    let stopped = false;
    return new TransformStream({
      transform(chunk, controller) {
        if (stopped) {
          return;
        }
        if (chunk.type === "text-delta") {
          const text = chunk.text || chunk.delta || "";
          accumulatedText += text;
          tokenCount = tokenizer(accumulatedText);
          if (tokenCount > maxTokens) {
            stopped = true;
            onBudgetExceeded?.({ consumed: tokenCount, budget: maxTokens });
            controller.enqueue({
              type: "error",
              error: `Token budget exceeded: ${tokenCount} > ${maxTokens}`
            });
            stopStream();
            return;
          }
        }
        controller.enqueue(chunk);
      }
    });
  };
}
function createTokenAwareGuardrailTransform(guardrails, options = {}) {
  const {
    checkEveryTokens = 10,
    maxTokens,
    stopOnSeverity = "critical",
    stopCondition,
    onViolation,
    tokenizer = estimateTokenCount,
    timeout = 5e3,
    parallel: parallel2 = true
  } = options;
  const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
  const minLevel = severityOrder[stopOnSeverity];
  return ({ stopStream }) => {
    let accumulatedText = "";
    let tokenCount = 0;
    let lastCheckTokens = 0;
    let stopped = false;
    return new TransformStream({
      async transform(chunk, controller) {
        if (stopped) {
          return;
        }
        if (chunk.type !== "text-delta") {
          controller.enqueue(chunk);
          return;
        }
        const text = chunk.text || chunk.delta || "";
        accumulatedText += text;
        tokenCount = tokenizer(accumulatedText);
        if (typeof maxTokens === "number" && tokenCount > maxTokens) {
          stopped = true;
          controller.enqueue({
            type: "error",
            error: `Token limit exceeded: ${tokenCount} > ${maxTokens}`
          });
          stopStream();
          return;
        }
        const tokensSinceLastCheck = tokenCount - lastCheckTokens;
        if (tokensSinceLastCheck < checkEveryTokens) {
          controller.enqueue(chunk);
          return;
        }
        lastCheckTokens = tokenCount;
        try {
          const mockResult = {
            text: accumulatedText,
            content: [],
            finishReason: "stop",
            usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }
          };
          const context = {
            input: {
              prompt: "",
              messages: [],
              system: ""
            },
            result: mockResult
          };
          const results = await executeOutputGuardrails(guardrails, context, {
            parallel: parallel2,
            timeout,
            continueOnFailure: true,
            logLevel: "none"
          });
          const summary = {
            allResults: results,
            blockedResults: results.filter((r) => r.tripwireTriggered),
            totalExecutionTime: 0,
            guardrailsExecuted: results.length,
            stats: {
              passed: results.filter((r) => !r.tripwireTriggered).length,
              blocked: results.filter((r) => r.tripwireTriggered).length,
              failed: 0,
              averageExecutionTime: 0
            }
          };
          const shouldStop = stopCondition ? stopCondition(summary) : summary.blockedResults.some((result) => {
            const resultSeverity = result.severity ?? "medium";
            return severityOrder[resultSeverity] >= minLevel;
          });
          if (shouldStop) {
            stopped = true;
            onViolation?.(summary);
            controller.enqueue({
              type: "error",
              error: `Guardrail violation: ${summary.blockedResults.map((r) => r.message).join(", ")}`
            });
            stopStream();
            return;
          }
          controller.enqueue(chunk);
        } catch (error) {
          console.error("Token-aware guardrail error:", error);
          controller.enqueue(chunk);
        }
      }
    });
  };
}

// src/guardrails/stream-transform.ts
function createGuardrailTransform(guardrails, options = {}) {
  const {
    onViolation = "stop",
    redactPatterns = [],
    redactionText = "[REDACTED]",
    replacementText = "[Content filtered]",
    minCharsBeforeCheck = 0,
    checkEveryNChunks = 1,
    requestContext,
    onStreamStopped,
    onViolationDetected
  } = options;
  return ({ stopStream }) => {
    let accumulatedText = "";
    let chunkCount = 0;
    const violations = [];
    let stopped = false;
    const context = {
      accumulatedText: "",
      chunkCount: 0,
      violations: [],
      requestContext
    };
    return new TransformStream({
      async transform(chunk, controller) {
        if (stopped) {
          return;
        }
        const chunkText = chunk.delta || chunk.textDelta || chunk.text || "";
        if (chunk.type === "text-delta" || chunk.type === "text") {
          accumulatedText += chunkText;
          chunkCount++;
          context.accumulatedText = accumulatedText;
          context.chunkCount = chunkCount;
          context.violations = violations;
          const shouldCheck = accumulatedText.length >= minCharsBeforeCheck && chunkCount % checkEveryNChunks === 0;
          if (shouldCheck && guardrails.length > 0) {
            for (const guardrail of guardrails) {
              if (guardrail.enabled === false) continue;
              try {
                const result = await guardrail.execute(
                  {
                    input: {
                      prompt: "",
                      messages: [],
                      system: "",
                      requestContext
                    },
                    result: { text: accumulatedText }
                  },
                  accumulatedText
                );
                if (result.tripwireTriggered) {
                  violations.push(result);
                  context.violations = violations;
                  if (onViolationDetected) {
                    onViolationDetected(result, chunk);
                  }
                  const handlerResult = await handleViolation(
                    chunk,
                    result,
                    context,
                    {
                      onViolation,
                      redactPatterns,
                      redactionText,
                      replacementText
                    }
                  );
                  switch (handlerResult.action) {
                    case "stop":
                      stopped = true;
                      stopStream();
                      if (onStreamStopped) {
                        onStreamStopped(violations, accumulatedText);
                      }
                      controller.enqueue({
                        ...chunk,
                        type: "text-delta",
                        delta: `
[Stream stopped: ${handlerResult.reason || result.message}]`
                      });
                      return;
                    case "drop":
                      return;
                    case "replace":
                      controller.enqueue({
                        ...chunk,
                        delta: handlerResult.replacement || replacementText,
                        textDelta: handlerResult.replacement || replacementText
                      });
                      return;
                    case "pass":
                    default:
                      break;
                  }
                }
              } catch (error) {
                console.error(`Guardrail "${guardrail.name}" error:`, error);
              }
            }
          }
          if (redactPatterns.length > 0 && chunkText) {
            const redactedText = applyRedaction(
              chunkText,
              redactPatterns,
              redactionText
            );
            if (redactedText !== chunkText) {
              controller.enqueue({
                ...chunk,
                delta: redactedText,
                textDelta: redactedText
              });
              return;
            }
          }
        }
        controller.enqueue(chunk);
      },
      flush(controller) {
        if (stopped && violations.length > 0) {
        }
      }
    });
  };
}
async function handleViolation(chunk, violation, context, options) {
  const { onViolation, redactPatterns, redactionText, replacementText } = options;
  if (typeof onViolation === "function") {
    return onViolation(chunk, violation, context);
  }
  switch (onViolation) {
    case "stop":
      return { action: "stop", reason: violation.message };
    case "drop":
      return { action: "drop", reason: violation.message };
    case "redact":
      const chunkText = chunk.delta || chunk.textDelta || "";
      const redacted = applyRedaction(chunkText, redactPatterns, redactionText);
      if (redacted !== chunkText) {
        return {
          action: "replace",
          replacement: redacted,
          reason: "Content redacted"
        };
      }
      return { action: "pass" };
    case "replace":
      return {
        action: "replace",
        replacement: replacementText,
        reason: violation.message
      };
    default:
      return { action: "pass" };
  }
}
function applyRedaction(text, patterns, redactionText) {
  let result = text;
  for (const pattern of patterns) {
    if (typeof pattern === "string") {
      result = result.split(pattern).join(redactionText);
    } else {
      result = result.replace(pattern, () => redactionText);
    }
  }
  return result;
}
var PII_PATTERNS = {
  /** US Social Security Number */
  SSN: /\b\d{3}-\d{2}-\d{4}\b/g,
  /** Email addresses */
  EMAIL: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
  /** Phone numbers (various formats) */
  PHONE: /\b(\+\d{1,2}\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}\b/g,
  /** Credit card numbers */
  CREDIT_CARD: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,
  /** IP addresses */
  IP_ADDRESS: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g,
  /** API keys (generic pattern) */
  API_KEY: /\b(sk|pk|api)[_-]?[a-zA-Z0-9]{20,}\b/gi
};
function createPIIRedactionTransform(options = {}) {
  const patterns = options.patterns || [
    PII_PATTERNS.SSN,
    PII_PATTERNS.EMAIL,
    PII_PATTERNS.PHONE,
    PII_PATTERNS.CREDIT_CARD
  ];
  return createGuardrailTransform([], {
    onViolation: "redact",
    // No guardrails, just pattern redaction
    redactPatterns: patterns,
    redactionText: options.redactionText || "[REDACTED]",
    requestContext: options.requestContext
  });
}
function createContentFilterTransform(options) {
  const {
    blockedKeywords,
    caseSensitive = false,
    onBlocked,
    requestContext
  } = options;
  return ({ stopStream }) => {
    let accumulatedText = "";
    let stopped = false;
    return new TransformStream({
      transform(chunk, controller) {
        if (stopped) return;
        const chunkText = chunk.delta || chunk.textDelta || chunk.text || "";
        if (chunk.type === "text-delta" || chunk.type === "text") {
          accumulatedText += chunkText;
          const textToCheck = caseSensitive ? accumulatedText : accumulatedText.toLowerCase();
          for (const keyword of blockedKeywords) {
            const keywordToCheck = caseSensitive ? keyword : keyword.toLowerCase();
            if (textToCheck.includes(keywordToCheck)) {
              stopped = true;
              stopStream();
              if (onBlocked) {
                onBlocked(keyword, accumulatedText);
              }
              controller.enqueue({
                ...chunk,
                type: "text-delta",
                delta: `
[Content blocked: prohibited content detected]`
              });
              return;
            }
          }
        }
        controller.enqueue(chunk);
      }
    });
  };
}

// src/guardrails/prepare-step.ts
function createGuardrailPrepareStep(violations, options = {}) {
  const {
    lookback = 2,
    temperatureReduction = 0.3,
    stopOnCritical = false,
    warningMessage = "Previous responses violated guidelines. Please be more careful and follow all safety guidelines."
  } = options;
  return ({ stepNumber }) => {
    const recentViolations = violations.filter((v) => {
      if ("step" in v) {
        return v.step >= stepNumber - lookback && v.step < stepNumber;
      }
      return false;
    });
    if (recentViolations.length === 0) {
      return;
    }
    const hasCritical = recentViolations.some(
      (v) => v.summary.blockedResults.some((r) => r.severity === "critical")
    );
    const result = {
      temperature: temperatureReduction,
      system: warningMessage
    };
    if (hasCritical && stopOnCritical) {
      result.stopWhen = () => true;
    }
    return result;
  };
}
function createAdaptivePrepareStep(options) {
  const {
    violations,
    strategy,
    onViolationDetected,
    escalateAfter = 5,
    lookback = 3
  } = options;
  return ({ stepNumber }) => {
    const recentViolations = violations.filter((v) => {
      if ("step" in v) {
        return v.step >= stepNumber - lookback && v.step < stepNumber;
      }
      return false;
    });
    if (recentViolations.length === 0) {
      return;
    }
    onViolationDetected?.(recentViolations);
    if (strategy) {
      return strategy(recentViolations);
    }
    const violationCount = recentViolations.length;
    const temperatureReduction = Math.max(0.1, 0.7 - violationCount * 0.15);
    const result = {
      temperature: temperatureReduction,
      system: `Warning: ${violationCount} guardrail violation(s) detected in recent steps. Please ensure responses comply with all safety guidelines.`
    };
    if (violationCount >= escalateAfter) {
      result.stopWhen = () => true;
      result.system += " Execution will stop due to repeated violations.";
    }
    return result;
  };
}

// src/guardrails/tool-abortion.ts
var ToolAbortionController = class {
  controller;
  minSeverity;
  timeout;
  constructor(options = {}) {
    this.controller = new AbortController();
    this.minSeverity = options.minSeverity ?? "critical";
    this.timeout = options.timeout ?? 3e3;
  }
  get signal() {
    return this.controller.signal;
  }
  /**
   * Check guardrails and abort if violations detected
   */
  async checkAndAbort(guardrails, context) {
    const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
    const minLevel = severityOrder[this.minSeverity];
    const results = await executeOutputGuardrails(guardrails, context, {
      parallel: true,
      timeout: this.timeout,
      continueOnFailure: true,
      logLevel: "none"
    });
    const shouldAbort = results.some((result) => {
      if (!result.tripwireTriggered) return false;
      const resultSeverity = result.severity ?? "medium";
      return severityOrder[resultSeverity] >= minLevel;
    });
    if (shouldAbort) {
      this.controller.abort("Guardrail violation detected");
      return true;
    }
    return false;
  }
  /**
   * Manually abort
   */
  abort(reason) {
    this.controller.abort(reason);
  }
};
function createToolAbortionController(options) {
  return new ToolAbortionController(options);
}
function wrapToolWithAbortion(tool, guardrails, options = {}) {
  const {
    checkBefore = false,
    monitorDuring = false,
    monitorInterval = 100,
    checkInputDelta = false,
    abortOnSeverity = "critical",
    timeout = 3e3
  } = options;
  const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
  const minLevel = severityOrder[abortOnSeverity];
  const originalExecute = tool.execute;
  const originalOnInputDelta = tool.onInputDelta;
  async function checkGuardrails(input) {
    const mockResult = {
      text: JSON.stringify(input),
      content: [],
      finishReason: "stop",
      usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }
    };
    const context = {
      input: {
        prompt: "",
        messages: [],
        system: ""
      },
      result: mockResult
    };
    const results = await executeOutputGuardrails(guardrails, context, {
      parallel: true,
      timeout,
      continueOnFailure: true,
      logLevel: "none"
    });
    const shouldAbort = results.some((result) => {
      if (!result.tripwireTriggered) return false;
      const resultSeverity = result.severity ?? "medium";
      return severityOrder[resultSeverity] >= minLevel;
    });
    if (shouldAbort) {
      const messages = results.filter((r) => r.tripwireTriggered).map((r) => r.message).join(", ");
      throw new Error(`Tool execution aborted: ${messages}`);
    }
  }
  const wrappedExecute = async (input, executeOptions) => {
    if (checkBefore) {
      await checkGuardrails(input);
    }
    const internalController = new AbortController();
    let monitorInterval_;
    let monitorError;
    if (monitorDuring) {
      monitorInterval_ = setInterval(async () => {
        try {
          await checkGuardrails(input);
        } catch (error) {
          monitorError = error;
          internalController.abort();
          clearInterval(monitorInterval_);
        }
      }, monitorInterval);
    }
    try {
      const combinedSignal = monitorDuring && executeOptions?.abortSignal ? AbortSignal.any([
        executeOptions.abortSignal,
        internalController.signal
      ]) : executeOptions?.abortSignal ?? (monitorDuring ? internalController.signal : void 0);
      const callOptions = combinedSignal ? { ...executeOptions, abortSignal: combinedSignal } : executeOptions;
      const result = await originalExecute.call(tool, input, callOptions);
      if (monitorInterval_) {
        clearInterval(monitorInterval_);
      }
      if (monitorError) {
        throw monitorError;
      }
      return result;
    } catch (error) {
      if (monitorInterval_) {
        clearInterval(monitorInterval_);
      }
      throw monitorError ?? error;
    }
  };
  const wrappedOnInputDelta = checkInputDelta && originalOnInputDelta ? async (deltaOptions) => {
    const mockResult = {
      text: deltaOptions.inputTextDelta,
      content: [],
      finishReason: "stop",
      usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }
    };
    const context = {
      input: {
        prompt: "",
        messages: [],
        system: ""
      },
      result: mockResult
    };
    const results = await executeOutputGuardrails(guardrails, context, {
      parallel: true,
      timeout,
      continueOnFailure: true,
      logLevel: "none"
    });
    const shouldAbort = results.some((result) => {
      if (!result.tripwireTriggered) return false;
      const resultSeverity = result.severity ?? "medium";
      return severityOrder[resultSeverity] >= minLevel;
    });
    if (shouldAbort) {
      const violation = results.find((r) => r.tripwireTriggered);
      throw new Error(
        `Tool input delta blocked by guardrail: ${violation?.message || "Guardrail violation"}`
      );
    }
    await originalOnInputDelta?.call(tool, deltaOptions);
  } : originalOnInputDelta;
  return {
    ...tool,
    execute: wrappedExecute,
    ...wrappedOnInputDelta && { onInputDelta: wrappedOnInputDelta }
  };
}

// src/guardrails/abort-controller.ts
var GuardrailViolationAbort = class extends Error {
  summary;
  constructor(summary) {
    const messages = summary.blockedResults.map((r) => r.message).filter(Boolean).join(", ");
    super(`Guardrail violation: ${messages}`);
    this.name = "GuardrailViolationAbort";
    this.summary = summary;
  }
};
function createGuardrailAbortController() {
  const controller = new AbortController();
  return {
    /**
     * The AbortSignal that can be passed to AI SDK functions
     */
    signal: controller.signal,
    /**
     * Creates a callback that aborts on violations of specified severity or higher
     *
     * @param minSeverity - Minimum severity to trigger abort (default: 'critical')
     * @returns Callback function for use with onInputBlocked/onOutputBlocked
     *
     * @example
     * ```typescript
     * const { signal, abortOnViolation } = createGuardrailAbortController();
     *
     * withGuardrails({ model,
     *   outputGuardrails: [toxicityFilter()],
     *   onOutputBlocked: abortOnViolation('high'), // Abort on high or critical
     * });
     * ```
     */
    abortOnViolation: (minSeverity = "critical") => {
      const severityOrder = { low: 1, medium: 2, high: 3, critical: 4 };
      const minLevel = severityOrder[minSeverity];
      return (summary) => {
        const hasViolation = summary.blockedResults.some((result) => {
          const resultSeverity = result.severity ?? "medium";
          return severityOrder[resultSeverity] >= minLevel;
        });
        if (hasViolation) {
          controller.abort(new GuardrailViolationAbort(summary));
        }
      };
    },
    /**
     * Creates a callback that aborts based on custom condition
     *
     * @param condition - Function that returns true to trigger abort
     * @returns Callback function for use with onInputBlocked/onOutputBlocked
     *
     * @example
     * ```typescript
     * const { signal, abortOnCondition } = createGuardrailAbortController();
     *
     * withGuardrails({ model,
     *   outputGuardrails: [qualityCheck()],
     *   onOutputBlocked: abortOnCondition(
     *     (summary) => summary.blockedResults.length > 2
     *   ),
     * });
     * ```
     */
    abortOnCondition: (condition) => {
      return (summary) => {
        if (condition(summary)) {
          controller.abort(new GuardrailViolationAbort(summary));
        }
      };
    },
    /**
     * Manually abort with custom reason
     *
     * @param reason - Custom abort reason
     *
     * @example
     * ```typescript
     * const { abort } = createGuardrailAbortController();
     * abort('User requested cancellation');
     * ```
     */
    abort: (reason) => {
      controller.abort(reason);
    }
  };
}

// src/guardrails/finish-reason.ts
function getGuardrailFinishReason(summary, options) {
  const { blocked = "content_filter", success = "stop" } = options ?? {};
  if (summary.blockedResults.length > 0) {
    return blocked;
  }
  return success;
}
function createGuardrailProviderMetadata(summary, options) {
  const { includeMetadata = false, includeStats = true } = options ?? {};
  const violations = summary.blockedResults.map((result) => {
    const violation = {
      message: result.message,
      severity: result.severity,
      guardrailName: result.context?.guardrailName
    };
    if (includeMetadata && result.metadata) {
      violation.metadata = result.metadata;
    }
    return violation;
  });
  return {
    guardrails: {
      blocked: summary.blockedResults.length > 0,
      violations,
      executionTime: summary.totalExecutionTime,
      guardrailsExecuted: summary.guardrailsExecuted,
      ...includeStats && { stats: summary.stats }
    }
  };
}
function createFinishReasonEnhancement(summary, result, options) {
  if (summary.blockedResults.length === 0) {
    return result;
  }
  const finishReason = getGuardrailFinishReason(summary, options);
  const guardrailMetadata = createGuardrailProviderMetadata(summary, options);
  return {
    ...result,
    finishReason,
    providerMetadata: result.providerMetadata ? { ...result.providerMetadata, ...guardrailMetadata } : guardrailMetadata
  };
}

// src/guardrails/tool-parameters.ts
function matchesToolName(guardrailToolName, toolName) {
  if (typeof guardrailToolName === "string") {
    return guardrailToolName === toolName || guardrailToolName === "*";
  }
  if (guardrailToolName instanceof RegExp) {
    return guardrailToolName.test(toolName);
  }
  if (Array.isArray(guardrailToolName)) {
    return guardrailToolName.includes(toolName);
  }
  return false;
}
function withToolParameterGuardrails(tools, guardrails, options = {}) {
  const { throwOnInvalid = true, onValidationFailed, requestContext } = options;
  const wrappedTools = {};
  for (const [toolName, tool] of Object.entries(tools)) {
    const originalTool = tool;
    const applicableGuardrails = guardrails.filter(
      (g) => matchesToolName(g.toolName, toolName)
    );
    if (applicableGuardrails.length === 0) {
      wrappedTools[toolName] = tool;
      continue;
    }
    wrappedTools[toolName] = {
      ...originalTool,
      execute: async (input, execOptions) => {
        const context = {
          toolName,
          requestContext
        };
        let currentInput = input;
        const failedResults = [];
        for (const guardrail of applicableGuardrails) {
          const result = await guardrail.validateInput(currentInput, context);
          if (!result.valid) {
            failedResults.push(result);
            if (result.block) {
              if (onValidationFailed) {
                onValidationFailed(toolName, input, [result]);
              }
              if (throwOnInvalid) {
                throw new ToolParameterValidationError(
                  toolName,
                  guardrail.name,
                  result.message || "Validation failed",
                  result.severity
                );
              }
              return {
                error: `Tool parameter validation failed: ${result.message}`,
                blocked: true,
                guardrail: guardrail.name
              };
            }
          } else if (result.sanitizedInput !== void 0) {
            currentInput = result.sanitizedInput;
          }
        }
        if (failedResults.length > 0) {
          if (onValidationFailed) {
            onValidationFailed(toolName, input, failedResults);
          }
          if (throwOnInvalid) {
            const messages = failedResults.map((r) => r.message).join("; ");
            throw new ToolParameterValidationError(
              toolName,
              "multiple",
              messages,
              failedResults[0]?.severity
            );
          }
        }
        return originalTool.execute(currentInput, execOptions);
      }
    };
  }
  return wrappedTools;
}
var ToolParameterValidationError = class extends Error {
  constructor(toolName, guardrailName, message, severity) {
    super(
      `Tool "${toolName}" parameter validation failed (${guardrailName}): ${message}`
    );
    this.toolName = toolName;
    this.guardrailName = guardrailName;
    this.severity = severity;
    this.name = "ToolParameterValidationError";
  }
  toolName;
  guardrailName;
  severity;
};

// src/backoff.ts
function exponentialBackoff(options = {}) {
  const { base = 1e3, max = 3e4, jitter = 0, multiplier = 2 } = options;
  return (attempt) => {
    const exponentialDelay = base * Math.pow(multiplier, attempt - 1);
    const cappedDelay = Math.min(exponentialDelay, max);
    if (jitter > 0) {
      const jitterAmount = cappedDelay * jitter * Math.random();
      return Math.round(
        cappedDelay + jitterAmount - cappedDelay * jitter / 2
      );
    }
    return cappedDelay;
  };
}
function linearBackoff(options = {}) {
  const { base = 1e3, max = 3e4, jitter = 0 } = options;
  return (attempt) => {
    const linearDelay = base * attempt;
    const cappedDelay = Math.min(linearDelay, max);
    if (jitter > 0) {
      const jitterAmount = cappedDelay * jitter * Math.random();
      return Math.round(
        cappedDelay + jitterAmount - cappedDelay * jitter / 2
      );
    }
    return cappedDelay;
  };
}
function fixedBackoff(options = {}) {
  const { base = 1e3, jitter = 0 } = options;
  return (_attempt) => {
    if (jitter > 0) {
      const jitterAmount = base * jitter * Math.random();
      return Math.round(base + jitterAmount - base * jitter / 2);
    }
    return base;
  };
}
function noBackoff() {
  return (_attempt) => 0;
}
function compositeBackoff(strategies) {
  return (attempt) => {
    for (const strategy of strategies) {
      if (attempt <= strategy.maxAttempts) {
        return strategy.backoff(attempt);
      }
    }
    const lastStrategy = strategies.at(-1);
    return lastStrategy ? lastStrategy.backoff(attempt) : 0;
  };
}
var jitteredExponentialBackoff = (options = {}) => exponentialBackoff({ ...options, jitter: 0.1 });
var presets = {
  /** Fast retry: 500ms, 1s, 2s, 4s (max 4s) */
  fast: () => exponentialBackoff({ base: 500, max: 4e3 }),
  /** Standard retry: 1s, 2s, 4s, 8s, 16s (max 16s) */
  standard: () => exponentialBackoff({ base: 1e3, max: 16e3 }),
  /** Slow retry: 2s, 4s, 8s, 16s, 32s (max 32s) */
  slow: () => exponentialBackoff({ base: 2e3, max: 32e3 }),
  /** Network resilient: jittered exponential with longer delays */
  networkResilient: () => jitteredExponentialBackoff({ base: 1e3, max: 3e4 }),
  /** Aggressive: very fast with short max delay for quick failures */
  aggressive: () => exponentialBackoff({ base: 200, max: 2e3 })
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  DEFAULT_DETECT_NORMALIZATION,
  GuardrailViolationAbort,
  PII_PATTERNS,
  ToolParameterValidationError,
  after,
  backoffPresets,
  clearViolationHistory,
  compositeBackoff,
  createAdaptivePrepareStep,
  createConsoleDebugger,
  createContentFilterTransform,
  createDebugWrapper,
  createDefaultBuildRetryParams,
  createFinishReasonEnhancement,
  createGuardrailAbortController,
  createGuardrailPrepareStep,
  createGuardrailProviderMetadata,
  createGuardrailStreamTransform,
  createGuardrailStreamTransformBuffered,
  createGuardrailTransform,
  createHealthCheck,
  createMetricsCollector,
  createPIIRedactionTransform,
  createPipeline,
  createTokenAwareGuardrailTransform,
  createTokenBudgetTransform,
  createToolAbortionController,
  detectSystemPromptLeak,
  enhancedPromptInjectionDetector,
  envDebugMode,
  estimateTokenCount,
  exponentialBackoff,
  fixedBackoff,
  formatTraceAsJSON,
  formatTraceForConsole,
  formatTraceSummary,
  getGuardrailFinishReason,
  getViolationStats,
  guardrailMiddleware,
  incrementalPromptInjectionDetector,
  inputGuardrailsMiddleware,
  inputPipeline,
  intentBasedInjectionDetector,
  jitteredExponentialBackoff,
  lenientEscalation,
  linearBackoff,
  logExecutionSummary,
  noBackoff,
  noopGuardrailMiddleware,
  normalizeForDetection,
  not,
  outputGuardrailsMiddleware,
  outputPipeline,
  parallel,
  resolveDetectNormalization,
  resolveRetryConfig,
  strictEscalation,
  toolCallInjectionDetector,
  warnOnly,
  when,
  withFallback,
  withGracePeriod,
  withGradualEnforcement,
  withRetry,
  withToolParameterGuardrails,
  wrapToolWithAbortion
});