All files / src/models/adapters base.ts

100% Statements 9/9
83.33% Branches 10/12
100% Functions 4/4
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86  10x                                                                             10x   10x                 100x 100x     141x       9x                           137x                 198x      
import { NimChatMessage } from "../../types";
import { parseTextEmbeddedToolCalls, ParsedTextToolCallResult } from "../../tools/parser";
 
export type ReasoningParameterFormat = "none" | "reasoning_effort" | "chat_template_kwargs";
 
export type ToolCallProtocol = "native-and-text" | "native-only";
 
export type ReasoningRouting = "direct-content" | "isolated" | "always-isolated";
 
export interface ModelAdapterCapabilityContract {
  readonly reasoningModes: readonly string[];
  readonly reasoningParameterFormat: ReasoningParameterFormat;
  readonly toolCallProtocol: ToolCallProtocol;
  readonly responseSanitization: "none" | "model-specific";
  readonly reasoningRouting: ReasoningRouting;
}
 
export interface NvidiaModelRequestProfile {
  defaultTemperature: number;
  toolTemperature?: number;
  extraSystemMessages: string[];
}
 
export interface ModelAdapter {
  readonly idPattern: RegExp;
  matches(modelId: string): boolean;
  getProfile(options: { toolsEnabled?: boolean }): NvidiaModelRequestProfile;
  applyMessagesWorkaround?(messages: NimChatMessage[]): NimChatMessage[];
  parseTextEmbeddedToolCalls?(text: string): ParsedTextToolCallResult;
  applyReasoningMode?(request: import("../../types").NimChatRequest, mode: string): void;
  sanitizeResponseText?(text: string): string;
  readonly supportedReasoningModes?: string[];
  readonly reasoningParameterFormat?: ReasoningParameterFormat;
  readonly toolCallProtocol?: ToolCallProtocol;
  readonly isolateUntaggedReasoning?: boolean;
  readonly alwaysReasons?: boolean;
 
  getCapabilityContract(): ModelAdapterCapabilityContract;
}
 
export const DEFAULT_TEMPERATURE = 0.7;
 
export abstract class BaseModelAdapter implements ModelAdapter {
  abstract readonly idPattern: RegExp;
  abstract readonly defaultTemperature: number;
  readonly toolTemperature?: number;
  readonly toolSystemMessage?: string;
  readonly supportedReasoningModes?: string[];
  readonly isolateUntaggedReasoning?: boolean;
  readonly alwaysReasons?: boolean;
  sanitizeResponseText?(text: string): string;
  readonly reasoningParameterFormat: ReasoningParameterFormat = "none";
  readonly toolCallProtocol: ToolCallProtocol = "native-and-text";
 
  parseTextEmbeddedToolCalls(text: string): ParsedTextToolCallResult {
    return parseTextEmbeddedToolCalls(text);
  }
 
  getCapabilityContract(): ModelAdapterCapabilityContract {
    return {
      reasoningModes: this.supportedReasoningModes ?? [],
      reasoningParameterFormat: this.reasoningParameterFormat,
      toolCallProtocol: this.toolCallProtocol,
      responseSanitization: this.sanitizeResponseText ? "model-specific" : "none",
      reasoningRouting: this.alwaysReasons
        ? "always-isolated"
        : this.isolateUntaggedReasoning === false
          ? "direct-content"
          : "isolated",
    };
  }
 
  getProfile(options: { toolsEnabled?: boolean }): NvidiaModelRequestProfile {
    return {
      defaultTemperature: this.defaultTemperature,
      toolTemperature: this.toolTemperature,
      extraSystemMessages:
        options.toolsEnabled && this.toolSystemMessage ? [this.toolSystemMessage] : [],
    };
  }
 
  matches(modelId: string): boolean {
    return this.idPattern.test(modelId);
  }
}