Skip to content

Core Classes ​

Essential classes for interacting with AI models, managing conversations, and building evaluations.

BaseModelRunner ​

The primary class for executing model interactions and generating responses.

Import ​

typescript
import { BaseModelRunner } from './core/cognition/runner.js';

Constructor ​

typescript
const runner = new BaseModelRunner(config?: Partial<ModelRunnerConfig>);

interface ModelRunnerConfig {
  rateLimitConfig?: RateLimitConfig;
  maxRetries?: number;    // default: 3
  maxTokens?: number;     // default: 4096
}

Methods ​

generateText(interaction: Interaction): Promise<ModelResponse> ​

Generate a text response from the model.

typescript
import { Stimulus } from './core/stimulus/stimulus.js';
import { Interaction } from './core/interaction/core/interaction.js';

const stimulus = new Stimulus({
  role: "helpful assistant",
  objective: "answer questions clearly"
});

const interaction = new Interaction(
  { name: "gemini-3-flash-preview", provider: "google" },
  stimulus
);

interaction.addMessage({
  role: 'user',
  content: 'Explain quantum computing'
});

const runner = new BaseModelRunner();
const response = await runner.generateText(interaction);

console.log(response.content);                    // Generated text
console.log(response.metadata.tokenUsage);         // { promptTokens, completionTokens, total }
console.log(response.metadata.cost?.totalCost);    // Cost in dollars

streamText(interaction: Interaction): Promise<ModelResponse> ​

Stream text responses with real-time output to stdout, then return the complete ModelResponse.

typescript
const runner = new BaseModelRunner();
const response = await runner.streamText(interaction);
// Text chunks are written to stdout during streaming
// response.content contains the full text when done
console.log(response.metadata.tokenUsage);

Streaming handles tool calls automatically — tool-call and tool-result messages are added to the interaction during the stream.

generateObject(interaction: Interaction, schema: ZodSchema): Promise<ModelResponse> ​

Generate structured output validated against a Zod schema.

typescript
import { z } from 'zod';

const TaskSchema = z.object({
  title: z.string(),
  priority: z.enum(['low', 'medium', 'high']),
  due_date: z.string().optional(),
  completed: z.boolean().default(false)
});

const runner = new BaseModelRunner();
const response = await runner.generateObject(interaction, TaskSchema);

// Structured output is returned as JSON in response.content
const task = JSON.parse(response.content);
console.log(task.title);
console.log(task.priority);

streamObject(interaction: Interaction, schema: ZodSchema): Promise<ModelResponse> ​

Generate structured output with streaming via partialObjectStream. Returns the complete result when done.

typescript
const runner = new BaseModelRunner();
const response = await runner.streamObject(interaction, TaskSchema);

// response.content is JSON string of the final object
const task = JSON.parse(response.content);

Uses partialObjectStream internally to avoid hanging issues. Partial objects are merged progressively to build the final result.

All Methods Return ModelResponse ​

Every runner method returns the same shape:

typescript
interface ModelResponse {
  content: string;              // Text or JSON string
  metadata: {
    startTime: Date;
    endTime: Date;
    tokenUsage: {
      promptTokens: number;
      completionTokens: number;
      total?: number;
    };
    cost?: CostBreakdown;
    provider: string;
    model: string;
  };
  reasoning?: string;           // Chain-of-thought (if supported)
  reasoningDetails?: Array<{
    type: 'text' | 'redacted';
    text?: string;
    data?: string;
    signature?: string;
  }>;
}

Interaction ​

Manages conversations with models. Requires both ModelDetails and a Stimulus object.

Import ​

typescript
import { Interaction } from './core/interaction/core/interaction.js';
import { Stimulus } from './core/stimulus/stimulus.js';

Constructor ​

typescript
constructor(modelDetails: ModelDetails, stimulus: Stimulus)

Create a new conversation:

typescript
import { ModelDetails } from './core/cognition/types.js';

const model: ModelDetails = {
  name: 'gemini-3-flash-preview',
  provider: 'google'
};

const stimulus = new Stimulus({
  role: "expert data analyst",
  objective: "analyze data and provide insights",
  instructions: [
    "Use statistical methods",
    "Explain findings clearly"
  ],
  temperature: 0.7,
  maxTokens: 1000
});

const interaction = new Interaction(model, stimulus);

High-Level Methods ​

The Interaction class has convenience methods that internally create a BaseModelRunner:

chat(message: string): Promise<ModelResponse> ​

Add a user message and get a response:

typescript
const response = await interaction.chat("Analyze this dataset");
console.log(response.content);

generateText(): Promise<ModelResponse> ​

Generate without adding a new user message (uses existing messages):

typescript
interaction.addMessage({ role: 'user', content: 'Hello' });
const response = await interaction.generateText();

streamText(): Promise<ModelResponse> ​

Stream with real-time output:

typescript
const response = await interaction.streamText();
console.log(response.content);  // Full text after streaming completes

generateObject(schema: ZodSchema): Promise<ModelResponse> ​

Generate structured output:

typescript
const response = await interaction.generateObject(AnalysisSchema);
const analysis = JSON.parse(response.content);

streamObject(schema: ZodSchema): Promise<ModelResponse> ​

Stream structured output:

typescript
const response = await interaction.streamObject(TaskSchema);
const task = JSON.parse(response.content);

Message Management ​

addMessage(message: CoreMessage): void ​

Add a message to the conversation:

typescript
interaction.addMessage({
  role: 'user',
  content: 'Analyze this data and provide insights'
});

interaction.addMessage({
  role: 'assistant',
  content: 'Based on the data, I can see...'
});

getMessages(): CoreMessage[] ​

Get all messages in the conversation.

addAttachmentFromPath(filePath: string): Promise<void> ​

Attach a file from the filesystem:

typescript
await interaction.addAttachmentFromPath('./chart.png');
await interaction.addAttachmentFromPath('./report.pdf');

Supported file types: JPG, JPEG, PNG, WebP, GIF (images), PDF (documents).

Context Management ​

typescript
// Set checkpoint before a long conversation
interaction.setCheckpoint();

// ... have conversation ...

// Compact context to manage token usage
const result = await interaction.compactContext();

if (result) {
  console.log(`Compacted segment [${result.segmentStart}..${result.segmentEnd}]`);
  console.log(`Replaced with ${result.replacementCount} message(s)`);
}

Tools ​

typescript
// Check if interaction has tools
interaction.hasTools();       // boolean

// Get Vercel AI SDK tools
interaction.getVercelTools(); // Record<string, Tool>

// Set max tool steps
interaction.setMaxSteps(10);

// Set output format for structured generation
interaction.setOutputFormat(zodSchema);

Stimulus ​

Configuration object that defines AI behavior. Does not run anything — it's pure configuration.

Import ​

typescript
import { Stimulus } from './core/stimulus/stimulus.js';

Constructor ​

typescript
const stimulus = new Stimulus(options: StimulusOptions);

StimulusOptions ​

typescript
interface StimulusOptions {
  id?: string;
  name?: string;
  description?: string;
  role?: string;                    // System role
  objective?: string;               // What the AI should accomplish
  instructions?: string[];          // Specific behavioral instructions
  reasoning?: string;               // Reasoning style guidance
  output?: string[];                // Output format instructions
  examples?: (string | { input: string; output: string })[];

  // Tools
  tools?: Record<string, Tool>;     // Vercel AI SDK tools
  toolInstructions?: string[];      // Tool usage guidance
  maxToolSteps?: number;            // Max tool call rounds

  // Model options
  temperature?: number;
  maxTokens?: number;
  topP?: number;
  frequencyPenalty?: number;
  presencePenalty?: number;

  // Runner
  runnerType?: 'base';              // Compatibility-only; Interaction uses base runner

  // Context
  systemContext?: string;

  // Skills
  skills?: SkillDefinition[];
  skillsDirs?: string[];
  skillsFromGit?: string[];
  skillsCacheRoot?: string;
}

Key Methods ​

typescript
stimulus.getPrompt();     // Returns the assembled system prompt string
stimulus.getTools();      // Returns the tools record

Evaluation ​

Evaluation is owned by @umwelten/evaluation, not a core runner subclass. Use EvalSuite for declarative cached/scored tasks and runFullEval for the standard benchmark composition. See the Evaluation API.

Types and Interfaces ​

ModelDetails ​

typescript
interface ModelDetails {
  name: string;          // Model identifier (e.g., 'gemini-3-flash-preview')
  provider: string;      // Provider ('google', 'ollama', 'openrouter', 'lmstudio', 'llamabarn', 'llamaswap', 'github-models', 'fireworks', 'minimax')
  temperature?: number;  // Creativity/randomness (0-2)
  topP?: number;         // Nucleus sampling parameter
  topK?: number;         // Top-K sampling parameter
  numCtx?: number;       // Context token count (Ollama)
  description?: string;
  contextLength?: number;
  costs?: {
    promptTokens: number;       // Cost per million prompt tokens
    completionTokens: number;   // Cost per million completion tokens
  };
}

ModelResponse ​

typescript
interface ModelResponse {
  content: string;
  metadata: {
    startTime: Date;
    endTime: Date;
    tokenUsage: {
      promptTokens: number;
      completionTokens: number;
      total?: number;
    };
    cost?: {
      promptCost: number;
      completionCost: number;
      totalCost: number;
      usage: TokenUsage;
    };
    provider: string;
    model: string;
  };
  reasoning?: string;
  reasoningDetails?: Array<{
    type: 'text' | 'redacted';
    text?: string;
    data?: string;
    signature?: string;
  }>;
}

ModelRunner Interface ​

typescript
interface ModelRunner {
  generateText(interaction: Interaction): Promise<ModelResponse>;
  streamText(interaction: Interaction): Promise<ModelResponse>;
  generateObject(interaction: Interaction, schema: ZodSchema): Promise<ModelResponse>;
  streamObject(interaction: Interaction, schema: ZodSchema): Promise<ModelResponse>;
}

Next Steps ​

Released under the MIT License.