Member Junction
    Preparing search index...

    Turns off failover for a Decision Eval cell, as PinnedVendorPromptRunner does for a Prompt Eval cell.

    A cell that pins a model is a measurement of that model. AIDecisionRunner fails over according to the decision prompt's FailoverStrategy, which is right in production and wrong here: a run answered by another candidate still lands under the pinned cell's label. With failover off, a pinned candidate that fails is a failed run, which is a data point; one that silently answered elsewhere would be a corrupted one.

    getFailoverConfiguration is the runner's documented override point, so no production surface changes. Model pinning itself uses the runner's own mechanism, AIDecisionParams.override.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    _metadata: Metadata
    _promptRunQueue: BaseEntitySaveQueue
    _provider: IMetadataProvider | null

    Accessors

    • get DefaultLogCategory(): string

      The category logError records when the caller passes none. Override it so a runner's uncategorized errors are attributed to that runner rather than to the base.

      Returns string

    • get DefaultPromptTimeoutMS(): number | undefined

      Engine-level default model-call timeout, in milliseconds, applied when the caller supplies no AIPromptParams.timeoutMS. undefined (the default) means NO implicit bound — a prompt run with neither a timeout nor a cancellation token stays unbounded, exactly as before, so this change is behavior-preserving for existing callers.

      Subclasses (or a host application's runner subclass) can override this to impose a global safety ceiling on every prompt call.

      Returns number | undefined

    • get Provider(): IMetadataProvider

      Optional metadata provider override. Callers should set instance.Provider = providerToUse before invoking run methods in multi-provider contexts. Falls back to the global default provider when unset.

      Returns IMetadataProvider

    • set Provider(value: IMetadataProvider | null): void

      Parameters

      Returns void

    • get RequiredModelType(): string

      Decisions run only on Decision-type models.

      Returns string

    Methods

    • Records one call's usage on its run row, for runners whose calls are not chat calls: tokens; continuous units (seconds, characters, images) with the MJ: AI Usage Types row that names their measure; and a cost only when the driver gave one. With no usage nothing is recorded, so the cost stays empty and the row's save prices it from the model's cost rows, or declines to.

      Call it from the FinalizeRunRecord callback.

      Parameters

      Returns void

    • Asserts that the prompt's configured model type matches the runner's required model type. If prompt.AIModelTypeID is null or undefined, does not throw (the runner's required type applies). If prompt.AIModelTypeID is set and does not match RequiredModelTypeID, throws a descriptive error naming the prompt, the prompt's configured type (resolved to name if possible), and the runner's required type.

      Parameters

      Returns void

    • The error for a model call the caller cancelled. It is classified Cancelled — Fatal and not eligible for failover — so ErrorAnalyzer, the failover loop and the validation retries all stop on it rather than treating it as an unknown model error.

      Parameters

      • Optionalmessage: string

        The message to keep, when a driver already reported the cancellation.

      Returns Error & { errorInfo: AIErrorInfo }

    • Builds a unified, ordered list of model-vendor candidates based on all selection criteria. Uses a 3-phase approach to properly handle SelectionStrategy='Specific' with AIPromptModel priorities.

      Phase 1: Handle explicit model ID (highest priority) Phase 2: Check if SelectionStrategy='Specific' with AIPromptModel entries - use ONLY those with AIPromptModel priorities Phase 3: Use general selection strategy (fallback) - blended priorities from legacy behavior

      Parameters

      • prompt: MJAIPromptEntityExtended

        The AI prompt with selection criteria

      • OptionalexplicitModelId: string

        Explicitly specified model ID (highest priority)

      • OptionalconfigurationId: string

        Configuration ID for filtering

      • OptionalpreferredVendorId: string

        Preferred vendor ID

      • Optionalverbose: boolean

      Returns ModelVendorCandidate[]

      Ordered array of model-vendor candidates (highest priority first)

    • Calculates the delay before the next failover attempt.

      Parameters

      • attemptNumber: number

        The current attempt number (1-based)

      • baseDelaySeconds: number

        The base delay in seconds from configuration

      Returns number

      Delay in milliseconds before the next attempt

      Implements exponential backoff with jitter by default. The delay increases exponentially with each attempt and includes random jitter to prevent thundering herd problems. Override this method to implement custom delay logic.

    • Composes the caller-supplied cancellation token with the resolved model-call timeout into a single AbortSignal that bounds one model call. NEITHER bound is discarded:

      • caller token only → the caller's signal is used directly (behavior unchanged)
      • timeout only → an internal controller aborts after the timeout elapses
      • both → an internal controller relays the caller's abort AND fires on timeout; whichever happens first wins
      • neither → Signal is undefined and the call runs unbounded (legacy behavior)

      Implemented with an AbortController + relay listener rather than AbortSignal.any() so it works on Node 18 (where AbortSignal.any does not exist — it landed in Node 20.3).

      Parameters

      Returns ExecutionBound

    • Whether a driver needs its own API key. LLMDecision does not: it runs an MJ prompt whose chat models resolve their own credentials, as LLMReranker does.

      Parameters

      • driverClass: string

      Returns boolean

    • Finalizes a prompt-run record in memory immediately AND queues a fire-and-forget UPDATE on _promptRunQueue that re-applies the finalized state after any in-flight 'Running' INSERT and its finalizeSave reload complete.

      Applying the completion fields synchronously in memory ensures callers that inspect result.promptRun right after ExecutePrompt (such as BaseAgent.calculateTokenStats() reading TokensPromptRollup, TokensCompletionRollup, TotalCost, and Status) see the finalized values immediately without blocking on the database round-trip, while re-applying the captured snapshot inside _promptRunQueue.Update(promptRun, ...) guarantees an in-flight INSERT reload can never revert the persisted row back to 'Running'.

      In order, it sets: the completion timing (CompletedAt, ExecutionTimeMS); the outcome (Success, and Status = 'Completed' or 'Failed' from it); any pending failover fields; the subclass's result fields (applyResultFields, invoked once); and finally the token rollups and TotalCost.

      Parameters

      • promptRun: MJAIPromptRunEntityExtended
      • success: boolean

        Whether the call succeeded, as the runner judges it (the chat runner also requires its output to pass validation).

      • endTime: Date
      • executionTimeMS: number
      • applyResultFields: (promptRun: MJAIPromptRunEntityExtended) => void

        Sets the runner's own result columns. It can read the timing and outcome already set, and may refine them (for example ErrorDetails or Status = 'Cancelled'). It must be synchronous.

      Returns Promise<void>

    • Awaits all in-flight MJAIPromptRunEntityExtended INSERT and UPDATE operations queued on this runner's internal BaseEntitySaveQueue (_promptRunQueue) and clears the in-flight parent lookup table.

      Normal intra-step prompt execution is non-blocking (fire-and-forget); callers that own the outer lifecycle (such as BaseAgent at run completion, failure, cancellation, or compaction) call FlushPendingSaves() to guarantee every AIPromptRun row is durably settled before returning.

      Returns Promise<void>

    • Resolves the per-model-call timeout: the caller's AIPromptParams.timeoutMS, else the runner's DefaultPromptTimeoutMS. Non-positive / non-numeric values mean "no timeout".

      The bound is applied PER MODEL CALL (not per prompt execution), which mirrors the parallel path's existing taskTimeoutMS semantics: each failover candidate / validation retry gets a fresh budget rather than sharing one wall-clock window.

      NOTE (issue #3064): there is deliberately NO prompt-entity source here yet — the AIPrompt table has no TimeoutMS column today. Once a migration adds one and CodeGen regenerates the entity, this becomes prompt.TimeoutMS ?? params.timeoutMS ?? this.DefaultPromptTimeoutMS and every bound below starts honoring the per-prompt configuration with no other change.

      Parameters

      Returns number | undefined

    • Treats a driver that needs no credentials as always available.

      Parameters

      • driverClass: string
      • promptId: string | undefined
      • modelId: string | undefined
      • vendorId: string | undefined
      • Optionalparams: AIPromptParams

      Returns boolean

    • Whether a failure was caused by the caller cancelling the request: its classification is Cancelled, or the older shape drivers built before that type existed.

      Parameters

      Returns boolean

    • Checks if a model vendor is configured as an inference provider. Delegates to the memoized AIEngine.IsInferenceProvider helper so the "Inference Provider" vendor-type lookup happens once per engine load rather than on every candidate in every selection pass.

      Parameters

      Returns boolean

      true if the vendor is an inference provider

    • Helper method for enhanced error logging with metadata

      Parameters

      • error: string | Error
      • Optionaloptions: {
            category?: string;
            maxErrorLength?: number;
            metadata?: Record<string, any>;
            model?: MJAIModelEntityExtended;
            prompt?: MJAIPromptEntityExtended;
            severity?: "error" | "warning" | "critical";
        }

      Returns void

    • Logs a failover attempt for tracking and debugging.

      Parameters

      • promptId: string

        The ID of the prompt being executed

      • attempt: FailoverAttempt

        The failover attempt details

      • willRetry: boolean

        Whether another attempt will be made

      Returns void

      This method logs detailed information about each failover attempt to help with debugging and monitoring. Override this method to implement custom logging or integrate with external monitoring systems.

    • Internal logging helper that wraps LogStatusEx with verbose control

      Parameters

      • message: string

        The message to log

      • OptionalverboseOnly: boolean

        Whether this is a verbose-only message

      • Optionalparams: AIPromptParams

        Optional prompt parameters for custom verbose check

      Returns void

    • Waits for a model call, or rejects as soon as its bound aborts: with the bound's AIPromptTimeoutError when the timeout fired, else with a cancellation error. The call the runner stops waiting for is torn down only if its driver was handed the bound's signal.

      For any runner whose driver call is not already bounded by the driver itself.

      Type Parameters

      • T

      Parameters

      Returns Promise<T>

    • Resolves the runner's RequiredModelType name against AIEngine.Instance.ModelTypes (case-insensitive, trimmed) and returns its UUID. Callers compare models' AIModelTypeID with it using UUIDsEqual. Throws a descriptive error if the model type is not found in the engine metadata.

      Returns string

    • Resolves credentials for AI model execution using a hierarchical resolution system.

      Resolution priority (highest to lowest):

      1. Per-request override: params.credentialId
      2. Prompt-Model specific: AIPromptModel.CredentialID
      3. Model-Vendor specific: AIModelVendor.CredentialID
      4. Vendor default: AIVendor.CredentialID
      5. Legacy: params.apiKeys[] array
      6. Legacy: AI_VENDOR_API_KEY__ environment variables

      IMPORTANT: When ANY credential ID is found (priorities 1-4), the system uses the Credentials path and ignores legacy methods (priorities 5-6).

      Each tier is consulted only if CredentialScopeAllows the run's AIPromptParams.CredentialScope to use its source. Under 'RuntimeOnly' that leaves priority 1 and the apiKeys entry for this driver class; bindings, the vendor default and the environment are skipped.

      Parameters

      • driverClass: string

        The driver class name (e.g., 'OpenAILLM')

      • promptId: string | undefined

        The prompt ID for looking up AIPromptModel credentials

      • modelId: string | undefined

        The model ID for looking up AIPromptModel and AIModelVendor credentials

      • vendorId: string | undefined

        The vendor ID for looking up AIModelVendor and AIVendor credentials

      • params: AIPromptParams

        The prompt execution parameters containing contextUser and optional credentialId

      Returns Promise<string>

      The API key/configuration string to pass to the LLM constructor

    • The usage to record for one call: the driver's when it reports a quantity (tokens, or units in a measure), otherwise the runner's own count, which keeps any cost the driver gave. With neither, the driver's usage (possibly undefined) is returned, and nothing is invented.

      A runner counts what it can see without the driver: the images returned, or the characters it sent. The driver's figure wins because it is the vendor's own measure.

      Parameters

      • reported: ModelUsage | undefined

        The usage the driver returned, if any.

      • counted: ModelUsage | undefined

        The runner's own count as ModelUsage.ForMedia, or undefined when it has none.

      Returns ModelUsage | undefined

    • Selects candidate models for failover based on the strategy and current failure.

      Parameters

      • currentModel: MJAIModelEntityExtended

        The model that just failed

      • currentVendorId: string | undefined

        The vendor ID that just failed

      • strategy: "None" | "SameModelDifferentVendor" | "NextBestModel" | "PowerRank"

        The failover strategy to use

      • modelStrategy: "PreferDifferentModel" | "PreferSameModel" | "RequireSameModel" | undefined

        The model selection preference

      • allCandidates: ModelVendorCandidate[]

        All available model-vendor candidates

      • attemptHistory: FailoverAttempt[]

        History of previous failover attempts

      Returns ModelVendorCandidate[]

      Array of candidates sorted by priority (highest first)

      This method implements different strategies for selecting failover candidates:

      • SameModelDifferentVendor: Try the same model with different vendors
      • NextBestModel: Try different models in order of preference
      • PowerRank: Use the global power ranking of models

      Override this method to implement custom candidate selection logic.

    • Determines whether a failover attempt should be made based on the error and configuration.

      Parameters

      • error: Error

        The error that occurred during execution

      • config: FailoverConfiguration

        The failover configuration

      • attemptNumber: number

        The current attempt number (1-based)

      Returns boolean

      True if failover should be attempted, false otherwise

      This method uses the ErrorAnalyzer to classify errors and determine if they are eligible for failover based on the configured error scope. Override this method to implement custom failover decision logic.

    • Awaits all in-flight prompt-run saves queued by this runner instance. The normal execution path does NOT call this — prompt-run persistence is intentionally fire-and-forget. Exposed for tests and for callers that need the AIPromptRun rows durably written before proceeding.

      Returns Promise<void>