ModLens VisionProvider Interface: Methods, Types, and Implementation Patterns

The VisionProvider interface in src/providers/index.ts defines the common contract that all ModLens vision providers must satisfy, exposing both subprocess-based and in-process API execution patterns through optional methods like buildInvocation, execute, and parseOutput.

The ModLens repository (liustack/modlens) provides a unified framework for integrating vision language models through a single, extensible provider interface. The VisionProvider interface establishes the mandatory properties and optional methods that every provider—from CLI wrappers like antigravity-cli to direct API clients like gemini-api—must implement to participate in the analysis pipeline.

Core VisionProvider Interface Structure

The VisionProvider interface is defined in [src/providers/index.ts](https://github.com/liustack/modlens/blob/main/src/providers/index.ts) and serves as the central abstraction for all vision providers. It accommodates two distinct execution models: subprocess providers that spawn external CLI tools, and in-process providers that make direct API calls.

export interface VisionProvider {
    /** Human‑readable identifier (e.g. “antigravity-cli”). */
    name: string;
    /** Default model name used when the caller does not specify one. */
    defaultModel: string;

    /** Sub‑process providers: construct a child‑process command line. */
    buildInvocation?: (options: BuildProviderInvocationOptions) => ProviderInvocation;

    /** Sub‑process providers: turn raw stdout into structured output. */
    parseOutput?: (stdout: string) => ProviderParsedOutput;

    /** In‑process API providers: directly perform the request. */
    execute?: (options: BuildProviderInvocationOptions) => Promise<ProviderParsedOutput>;

    /** Turn a non‑zero exit or error into a friendly message. */
    describeFailure?: (context: ProviderFailureContext) => string | Error | null;

    /** Does the provider enforce its own timeout? (e.g. agy’s `--print-timeout`) */
    hasInternalTimeout?: boolean;

    /** Should the analyzer run the provider in an isolated work‑dir? */
    isolateWorkdir?: boolean;

    /** Optional warning shown when a route is reused from another harness. */
    reuseNote?: string;
}

Required Properties

Every VisionProvider implementation must define two core properties:

  • name: A human-readable string identifier (e.g., "antigravity-cli", "gemini-api") used for provider resolution and logging.
  • defaultModel: The default model name invoked when the caller does not explicitly specify one in BuildProviderInvocationOptions.

These properties appear at the top of every provider export, such as antigravityCliProvider in [src/providers/antigravity.ts](https://github.com/liustack/modlens/blob/main/src/providers/antigravity.ts).

Execution Patterns: Subprocess vs. In-Process

The interface supports two mutually exclusive execution strategies. Providers implement one pattern based on their underlying architecture.

Subprocess Providers

Subprocess providers wrap external CLI executables and must implement:

  • buildInvocation: A function accepting BuildProviderInvocationOptions and returning a ProviderInvocation object containing the command, args, cwd, and optional env for the child process.
  • parseOutput: A function that transforms raw stdout strings into structured ProviderParsedOutput objects according to the ModLens schema.

This pattern is used by providers like antigravity-cli, kimi-cli, and claude-cli, which shell out to local binaries.

In-Process API Providers

In-process API providers make direct HTTP calls or SDK invocations within the Node.js process and must implement:

  • execute: An async function accepting BuildProviderInvocationOptions and returning a Promise<ProviderParsedOutput> directly, bypassing subprocess management.

This pattern appears in [src/providers/geminiApi.ts](https://github.com/liustack/modlens/blob/main/src/providers/geminiApi.ts) and [src/providers/anthropicApi.ts](https://github.com/liustack/modlens/blob/main/src/providers/anthropicApi.ts), where the provider directly interfaces with cloud APIs.

Utility and Configuration Methods

The VisionProvider interface includes optional configuration flags and error handling utilities:

  • describeFailure: Transforms subprocess exit codes, stderr, or API errors into user-friendly messages. Accepts a ProviderFailureContext object containing stdout, stderr, code, and startedAt.
  • hasInternalTimeout: A boolean flag indicating whether the provider manages its own timeout logic (e.g., Antigravity's --print-timeout flag).
  • isolateWorkdir: When true, instructs the analyzer to execute the provider in an isolated temporary directory.
  • reuseNote: An optional warning string displayed when a test route is reused from another harness.

Supporting Types for Type Safety

The interface relies on several supporting types defined in the same [src/providers/index.ts](https://github.com/liustack/modlens/blob/main/src/providers/index.ts) file:

  • ProviderInvocation (lines 9‑15): Describes the child process configuration with command, args, cwd, and optional env.
  • BuildProviderInvocationOptions (lines 17‑28): Input parameters passed to both buildInvocation and execute, including imageSource, imageKind, timeoutMs, model, and extraPrompt.
  • ProviderParsedOutput (lines 30‑37): The normalized return structure containing the result string and optional metadata.
  • ProviderFailureContext (lines 40‑46): Context object for error handling with stdout, stderr, code, and startedAt timestamp.

Implementation Examples

Resolving a Provider by Name

Use the resolveProvider utility to retrieve a VisionProvider implementation by its string identifier:

import { resolveProvider } from './providers/index.ts';

const provider = resolveProvider('gemini-api');
console.log(provider.name);        // "gemini-api"
console.log(provider.defaultModel); // Default model for Gemini

Building Subprocess Commands

For CLI-based providers like antigravity-cli, construct the invocation using buildInvocation:

import { resolveProvider } from './providers/index.ts';
import type { BuildProviderInvocationOptions } from './providers/index.ts';

const options: BuildProviderInvocationOptions = {
  imageSource: '/tmp/screenshot.png',
  imageKind: 'local',
  timeoutMs: 30_000,
};

const provider = resolveProvider('antigravity-cli');
if (provider.buildInvocation) {
  const invocation = provider.buildInvocation(options);
  // Returns: { command: 'agy', args: ['--image', '/tmp/screenshot.png'], cwd: '/tmp' }
}

Executing Direct API Calls

For API providers like gemini-api, use the execute method for in-process requests:

import { resolveProvider } from './providers/index.ts';

const opts = {
  imageSource: 'https://example.com/image.jpg',
  imageKind: 'remote',
  timeoutMs: 20_000,
  model: 'gemini-1.5-flash',
};

const provider = resolveProvider('gemini-api');
if (provider.execute) {
  const result = await provider.execute(opts);
  console.log(result.result);   // Structured vision analysis
}

Handling Provider Failures

Implement graceful error handling using describeFailure:

import { resolveProvider } from './providers/index.ts';
import type { ProviderFailureContext } from './providers/index.ts';

const provider = resolveProvider('antigravity-cli');
if (provider.describeFailure) {
  const context: ProviderFailureContext = {
    stdout: '',
    stderr: 'quota exceeded',
    code: 1,
    startedAt: Date.now() - 5000,
  };
  const message = provider.describeFailure(context);
  console.warn(message);   // User-friendly error description
}

Concrete Provider Implementations

The ModLens repository includes several reference implementations conforming to VisionProvider:

Summary

  • The VisionProvider interface in src/providers/index.ts is the common contract all ModLens providers must implement.
  • Required properties are name and defaultModel; all execution methods are optional but providers must implement either the subprocess pair (buildInvocation/parseOutput) or the in-process method (execute).
  • Supporting types like ProviderInvocation, BuildProviderInvocationOptions, and ProviderFailureContext ensure type safety across the provider boundary.
  • Concrete implementations demonstrate both CLI-wrapping (antigravity-cli) and native API (gemini-api) patterns.
  • Optional flags like hasInternalTimeout and isolateWorkdir allow providers to signal specific runtime requirements to the analyzer.

Frequently Asked Questions

What is the difference between buildInvocation and execute in the ModLens VisionProvider interface?

buildInvocation is used by subprocess providers to construct a shell command (returning command, args, and cwd), while execute is used by in-process API providers to perform direct SDK or HTTP calls and return a Promise<ProviderParsedOutput>. A provider should implement one pattern or the other, never both.

How does the describeFailure method improve error handling in ModLens providers?

The describeFailure method receives a ProviderFailureContext object containing stdout, stderr, code, and startedAt, allowing providers to translate cryptic exit codes or API errors into actionable, user-friendly strings. If not implemented, the analyzer falls back to generic error messages.

Which providers in the ModLens repository implement the VisionProvider interface?

All concrete providers export an object conforming to VisionProvider, including antigravity-cli (src/providers/antigravity.ts), gemini-api (src/providers/geminiApi.ts), openai-compat (src/providers/openaiCompat.ts), anthropic-api (src/providers/anthropicApi.ts), kimi-cli, and claude-cli.

When should a provider set isolateWorkdir to true?

Set isolateWorkdir to true when the provider creates temporary files, modifies the filesystem, or requires a clean state between runs. This flag instructs the ModLens analyzer to execute the provider in a temporary directory that is cleaned up after execution, preventing state pollution.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →