@flink-app/openai-adapter

中文文档
2.0.0-alpha.134发布于 2026/11/07MITTypeScriptCommonJS近 30 天下载 3518

OpenAI adapter for Flink AI framework

原始使用文档
文档目录32 节
  1. Why Responses API?
  2. Important: Understanding the Agent Loop
  3. Installation
  4. Usage
  5. Basic Setup
  6. Agent Instructions
  7. Structured Outputs
  8. Reasoning
  9. Conversation Persistence (Recommended)
  10. Image Model
  11. Debug Logging
  12. Cache Metrics & Cost Optimization
  13. Multiple Adapters
  14. Using in Agents
  15. Supported Models
  16. GPT-6 Series (Recommended)
  17. GPT-5 Series
  18. GPT-4.1 Series
  19. O-Series Reasoning Models
  20. Legacy Models
  21. Model Selection Guide
  22. Features
  23. What Makes Responses API Different
  24. API
  25. OpenAIAdapter
  26. Architecture Notes
  27. Responses API vs Chat Completions
  28. Flink Integration
  29. Migration from Chat Completions
  30. Requirements
  31. License
  32. Resources

@flink-app/openai-adapter

OpenAI adapter for the Flink AI framework using the Responses API - OpenAI's modern API that provides step-aware reasoning, explicit tool invocation, and better performance.

Why Responses API?

This adapter uses OpenAI's Responses API instead of the older Chat Completions API, providing:

  • 🔧 Step-aware reasoning: Model returns multiple tool calls as explicit, typed items in a single response
  • ⚡ Better performance: 3% improvement on SWE-bench, 5% on TAUBench vs Chat Completions
  • 📦 First-class tool steps: Tool calls and results are structured items, not message hacks
  • 🎯 Future-proof: All new OpenAI features will land in Responses API first

Important: Understanding the Agent Loop

The Responses API does NOT run your agent loop.

What it provides:

  • Multiple tool calls in one response (you still execute them)
  • Structured step types (message, function_call, function_call_output)

What Flink handles (via AgentRunner):

  • Tool execution
  • Multi-turn loops (API → execute tools → API → execute tools → done)
  • Deciding when to stop
  • Managing conversation state

This separation is intentional - it gives you full control over agent behavior while leveraging better API primitives.

Installation

npm install @flink-app/openai-adapter
# or
pnpm add @flink-app/openai-adapter

The openai package is included as a dependency, so you don't need to install it separately.

Usage

Basic Setup

import { OpenAIAdapter } from "@flink-app/openai-adapter";
import { FlinkApp } from "@flink-app/flink";

const app = new FlinkApp({
  ai: {
    llms: {
      default: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "gpt-6-luna",
        reasoning: { effort: "none" }, // lowest latency for request/response use
      }),
    },
  },
});

await app.start();

Legacy API (still supported):

// Backward-compatible constructor
new OpenAIAdapter(process.env.OPENAI_API_KEY!, "gpt-5")

Agent Instructions

Define your agent's behavior using the instructions property:

// src/agents/support_agent.ts
export const Agent: FlinkAgentProps = {
  name: "support_agent",
  instructions: "You are a helpful customer support agent.",
  tools: ["get_order_status"],
  model: { adapterId: "default" },
};

How it works:

  • Instructions are prepended as a system message to every conversation
  • Follows Vercel AI SDK pattern for consistency
  • Provides stable agent behavior across all interactions

Dynamic Context with System Messages

For per-request context, add system messages to the conversation:

const result = await ctx.agents.myAgent.execute({
  message: [
    { role: "system", content: "Current user tier: Premium" },
    { role: "user", content: "What can I do?" }
  ]
});

Order of messages sent to OpenAI:

  1. Agent instructions (as system message)
  2. User-provided system messages (if any)
  3. Conversation messages

This gives you both static agent behavior and dynamic per-request context.

Structured Outputs

Enable structured outputs with JSON schema for 100% reliability in output format:

import { OpenAIAdapter } from "@flink-app/openai-adapter";

const adapter = new OpenAIAdapter({
  apiKey: process.env.OPENAI_API_KEY!,
  model: "gpt-5",
  structuredOutput: {
    type: "json_schema",
    name: "car_analysis",
    description: "Analysis of car specifications",
    schema: {
      type: "object",
      properties: {
        brand: { type: "string" },
        model: { type: "string" },
        year: { type: "number" },
        features: {
          type: "array",
          items: { type: "string" }
        }
      },
      required: ["brand", "model", "year"],
      additionalProperties: false
    },
    strict: true // Enforces 100% schema adherence
  }
});

The adapter option is a default for every call through this adapter. A structured output requested by the agent (model.structuredOutput, or execute({ model: { structuredOutput } })) takes precedence, so one adapter can serve any number of schemas; the parsed reply is available as result.structured. A per-call schema is sanitized to OpenAI's strict subset the same way tool schemas are (additionalProperties: false, all properties required, numeric/string constraints stripped); pass strict: false to send it verbatim. The constructor option is sent as given, unchanged from earlier releases.

The agent's model.toolChoice is sent as tool_choice ("auto", "none", "required" or { type: "function", name }) whenever the request carries tools.

Benefits of Structured Outputs:

  • 100% reliability (vs ~95% with JSON mode)
  • No need for retry logic or manual validation
  • Automatic schema validation during generation
  • Supported on all modern models: gpt-6-*, gpt-5.x, gpt-4.1, o4-mini, o3

Reasoning

Reasoning models (o-series, gpt-5, gpt-6 and later) are configured per adapter with the reasoning option, passed through verbatim as the Responses API reasoning parameter (SDK type, so new effort levels or summary modes need no adapter changes):

const adapter = new OpenAIAdapter({
  apiKey: process.env.OPENAI_API_KEY!,
  model: "gpt-6-luna",
  reasoning: { effort: "high", summary: "auto" }, // optional
  verbosity: "low", // optional, sent as text.verbosity
});
  • effort accepts the SDK's ReasoningEffort values: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" (the supported set is model-specific). Use "none" or "low" for RAG chat and other request/response flows where first-token latency and output tokens matter.

  • verbosity ("low" | "medium" | "high", gpt-5 and later) is sent as text.verbosity only when set, alongside any structured output format.

  • Temperature: reasoning models reject temperature, so the adapter only sends an agent's configured temperature to known non-reasoning models (gpt-4*, gpt-3.5*, *chat-latest). For every other model, including unknown future ids, it is dropped and a warning is logged.

  • summary makes the model return a reasoning summary, streamed as reasoning chunks and surfaced by the agent as reasoning_delta events on fullStream. It never appears in textStream or result.message.

  • When reasoning is set, include: ["reasoning.encrypted_content"] is added so reasoning items can be replayed even with store: false.

  • Reasoning items returned by the model (id, summary, encrypted content) are kept verbatim on the assistant message (providerData.openai.reasoningItems) and replayed ahead of the function calls they produced on later turns, as OpenAI recommends for tool-calling quality. Traces from other providers have no OpenAI item id and are skipped.

For multi-turn conversations, use ConversationAgent to automatically save conversation history:

// src/agents/ChatAgent.ts
import { ConversationAgent, ConversationData } from "@flink-app/flink";

export default class ChatAgent extends ConversationAgent<AppContext> {
    id = "chat-agent";
    description = "Chat assistant with automatic conversation persistence";
    instructions = "You are a helpful assistant...";
    tools = ["search-knowledge"];

    // Load conversation from your storage backend
    protected async loadConversation(conversationId: string) {
        const conv = await this.ctx.repos.conversationRepo.getById(conversationId);
        return conv ? {
            messages: conv.messages,
            providerMetadata: conv.providerMetadata // ← Preserved for tracking
        } : null;
    }

    // Save conversation with updated metadata
    protected async saveConversation(conversationId: string, data: ConversationData) {
        await this.ctx.repos.conversationRepo.upsert({
            _id: conversationId,
            messages: data.messages,
            providerMetadata: data.providerMetadata // ← Saved automatically
        });
    }
}

What this enables:

  1. Automatic History Management: Framework handles full conversation history
  2. Metadata Tracking: Provider metadata preserved for debugging and future use
  3. Storage Flexibility: Works with MongoDB, Redis, in-memory, or any backend
  4. Type Safety: Abstract methods enforce consistent implementation

Example Storage Backends:

How Provider Metadata Works:

  1. First turn: Agent executes, adapter may return provider-specific metadata
  2. saveConversation() stores messages + metadata
  3. Second turn: loadConversation() returns messages + metadata
  4. Framework populates input.providerMetadata for tracking/debugging
  5. Full conversation history is always sent for reliability

Note: Provider metadata is namespaced by adapter (e.g., { openai: {...}, anthropic: {...} }) for multi-provider support.

Image Model

OpenAIImageModel implements Flink's ImageModel interface on the Image API (images.generate / images.edit) for gpt-image-* models. Register it under ai.images and use it from ctx.ai.images:

import { OpenAIImageModel } from "@flink-app/openai-adapter";

const app = new FlinkApp<AppCtx>({
    ai: {
        images: {
            default: new OpenAIImageModel({
                apiKey: process.env.OPENAI_API_KEY!,
                model: "gpt-image-2",
                quality: "high", // optional defaults: quality, background, outputFormat
            }),
        },
    },
});

const { images, usage } = await ctx.ai.images.default.edit({
    prompt: "Replace the sky with a thunderstorm",
    images: [imageFromBuffer(file, "image/png")], // up to 16 reference images, the first is the edit target
    mask: imageFromBuffer(maskPng, "image/png"),  // optional, transparent areas are replaced
});
  • aspectRatio 1:1 / 3:2 / 2:3 map to Image API sizes; seed is not supported (both produce warnings)
  • Other parameters pass through providerOptions.openai (moderation, output_compression, ...)
  • Failures are ImageModelErrors; retryable is true for 429 / 5xx
  • See the Image Models guide

Debug Logging

The adapter includes component-specific logging to help debug API requests and responses:

const adapter = new OpenAIAdapter({
  apiKey: process.env.OPENAI_API_KEY!,
  model: "gpt-5",
  debug: true // Enable debug logging for this adapter
});

What gets logged:

When debug: true:

  • ✅ Initialization confirmation
  • ✅ Request metadata (model, message count, tool count, token limits)
  • ✅ Full request parameters sent to OpenAI
  • ✅ Tool call decisions made by the LLM
  • ✅ Token usage and performance metrics
  • ✅ Response IDs for conversation continuation
  • ✅ Error details with context

When debug: false (default):

  • ✅ Request completion with token usage (info level)
  • ✅ Errors with context

Log Output Example:

2026-02-15 [OpenAI] [INFO] OpenAI adapter initialized with debug logging enabled
2026-02-15 [OpenAI] [DEBUG] Starting OpenAI stream request {"model":"gpt-5","messageCount":2,"toolCount":3}
2026-02-15 [OpenAI] [DEBUG] Stream connection established
2026-02-15 [OpenAI] [DEBUG] LLM decided to call tool {"name":"get_weather","call_id":"call_abc123"}
2026-02-15 [OpenAI] [INFO] OpenAI request completed {"inputTokens":150,"outputTokens":80,"totalTokens":230}

Environment-Based Configuration:

You can also enable debug logging via environment variables without code changes:

# Enable debug for OpenAI adapter specifically
DEBUG=OpenAI npm start

# Enable debug for multiple components
DEBUG=OpenAI,Database npm start

# Set global log level
LOG_LEVEL=debug npm start

Programmatic Control:

For dynamic control at runtime:

import { FlinkLogFactory } from "@flink-app/flink";

// Enable debug for OpenAI adapter
FlinkLogFactory.setComponentLevel("OpenAI", "debug");

// Later, disable it
FlinkLogFactory.setComponentLevel("OpenAI", "info");

Benefits:

  • 🔍 Debug API requests without flooding other logs
  • 📊 Track token usage per request
  • 🐛 Investigate tool calling issues
  • ⚡ Monitor performance and latency
  • 🎯 Component-specific logging (OpenAI logs don't affect Database, Cache, etc.)

See Flink Logging Guide for more details on component-specific logging.

Cache Metrics & Cost Optimization

The OpenAI adapter automatically captures detailed cache metrics to help you optimize costs and understand performance:

const result = await ctx.agents.myAgent.execute({
  message: "What's the weather?"
});

console.log(result.usage);
// {
//   inputTokens: 2006,
//   outputTokens: 300,
//   cachedInputTokens: 1920  // 95% cache hit!
// }

// Calculate actual billed input tokens
const billedInputTokens = result.usage.inputTokens - (result.usage.cachedInputTokens || 0);
console.log(`Only ${billedInputTokens} tokens charged at full rate`);
// "Only 86 tokens charged at full rate"

// Estimate cost savings (cached tokens are ~10% of regular cost)
const regularCost = billedInputTokens * 1.0;
const cachedCost = (result.usage.cachedInputTokens || 0) * 0.1;
const totalCost = regularCost + cachedCost;
console.log(`Estimated cost factor: ${totalCost} (vs ${result.usage.inputTokens} without caching)`);
// "Estimated cost factor: 278 (vs 2006 without caching)" - 86% savings!

Cache Metrics:

  • inputTokens: Total input tokens (including cached)
  • outputTokens: Total output tokens
  • cachedInputTokens: Input tokens served from cache (10% cost)

OpenAI Caching:

  • Cached tokens cost ~10% of regular tokens
  • Automatic caching for repeated context
  • No configuration needed - OpenAI handles it automatically

When Caching Helps Most:

  • Long system prompts used across requests
  • Repeated context in multi-turn conversations
  • Few-shot examples in prompts
  • Large knowledge bases in context

Logging: When debug mode is enabled, cache metrics are automatically logged:

2026-02-23 [flink.ai.openai] [INFO] OpenAI request completed {
  "inputTokens": 2006,
  "outputTokens": 300,
  "cachedInputTokens": 1920,
  "totalTokens": 2306,
  "status": "completed",
  "model": "gpt-5"
}

Multiple Adapters

You can register multiple OpenAI adapters with different configurations:

import { OpenAIAdapter } from "@flink-app/openai-adapter";
import { FlinkApp } from "@flink-app/flink";

const app = new FlinkApp({
  ai: {
    llms: {
      // Default GPT-6 - best for general tasks
      default: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "gpt-6-luna",
        reasoning: { effort: "low" }
      }),

      // Fast reasoning model - cost-efficient
      fast: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "o4-mini"
      }),

      // Maximum intelligence for complex reasoning
      smart: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "o3"
      }),

      // With structured output
      structured: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "gpt-6-luna",
        structuredOutput: {
          type: "json_schema",
          name: "response",
          schema: { /* your schema */ },
          strict: true
        }
      }),
    },
  },
});

Using in Agents

Reference the adapter by its registered ID in your agent configuration:

// src/agents/support_agent.ts
import { FlinkAgentProps } from "@flink-app/flink";

export const Agent: FlinkAgentProps = {
  name: "support_agent",
  description: "Customer support assistant",
  instructions: "You are a helpful customer support agent.",
  tools: ["get_order_status", "search_knowledge_base"],
  model: {
    adapterId: "default", // Uses the "default" adapter
    maxTokens: 2000,
    temperature: 0.7, // ignored (with a warning) on reasoning models
  },
};

Supported Models

This adapter works with all OpenAI models available via the Responses API. The latest models (as of 2026) offer significant improvements:

  • gpt-6-astra, gpt-6.1-sol, gpt-6-sol, gpt-6-luna
    • OpenAI's current line-up; all are reasoning models
    • reasoning.effort accepts none, low, medium (default), high, xhigh and max

GPT-5 Series

  • GPT-5.6: gpt-5.6 - reasoning model, recommended replacement alongside GPT-6
  • GPT-5: gpt-5, gpt-5-mini, gpt-5-nano - shut down on 2026-12-11

GPT-4.1 Series

  • GPT-4.1: gpt-4.1

    • Smartest non-reasoning model
    • Excellent at coding tasks
    • Strong at precise instruction following
    • Best for web development and technical tasks
  • GPT-4.1 mini: gpt-4.1-mini

    • Smaller, faster, more cost-efficient
    • Good balance of capability and cost
  • GPT-4.1 nano: gpt-4.1-nano

    • Ultra-fast and cost-efficient
    • Best for simple, high-volume tasks

O-Series Reasoning Models

  • o4-mini: o4-mini (recommended for reasoning tasks)

    • Fast, cost-efficient reasoning model
    • Best-performing on AIME 2024 and 2025 benchmarks
    • Optimized for mathematical and logical reasoning
  • o3: o3

    • Advanced reasoning model for complex tasks
    • State-of-the-art performance on coding, math, and science
    • Excellent at Codeforces, SWE-bench, and MMMU
  • o3-pro: o3-pro

    • Premium reasoning model (Pro users only)
    • Designed to think longer and provide most reliable responses

Legacy Models

For backwards compatibility:

  • GPT-4 Turbo: gpt-4-turbo
  • GPT-4: gpt-4
  • GPT-3.5 Turbo: gpt-3.5-turbo

Note: Every GPT-4.1 and GPT-4o model shuts down on 2027-01-14. Migrate to GPT-6 or GPT-5.6 (see OpenAI deprecations).

Model Selection Guide

Use CaseRecommended ModelWhy
General developmentgpt-6-lunaCurrent generation
Low-latency chat / RAGgpt-6-luna with effort: "none"Minimal reasoning overhead
Coding & technicalgpt-4.1Best instruction following
High-volume tasksgpt-4.1-miniCost-efficient with good performance
Mathematical reasoningo4-miniOptimized for math, fast and cost-efficient
Complex problem-solvingo3State-of-the-art reasoning
Mission-criticalo3-proMaximum reliability (Pro users)

Features

  • ✅ Step-based tool calling - Multiple tool calls in one response as typed items
  • ✅ Event-based streaming - Proper event taxonomy (not just token streaming)
  • ✅ Structured outputs with JSON schema (100% reliability)
  • ✅ Reasoning - reasoning passthrough, summaries streamed as reasoning_delta, reasoning items replayed across turns
  • ✅ First-class tool steps - function_call and function_call_output as explicit types
  • ✅ Support for all OpenAI models (GPT-6, GPT-5.x, GPT-4.1, o-series)
  • ✅ 3-5% performance improvement over Chat Completions

What Makes Responses API Different

The key difference is how tool calls are represented, not who executes them:

Chat Completions (old):

Response: {
  message: {
    content: "...",
    tool_calls: [...]  // Tool calls embedded in message
  }
}

You: Extract tool calls, execute them, create new messages, call API again

Responses API (new):

Response: {
  output: [
    { type: "message", content: "..." },
    { type: "function_call", name: "...", call_id: "..." },
    { type: "function_call", name: "...", call_id: "..." }  // Multiple calls!
  ]
}

You: Extract tool calls, execute them, create function_call_output items, call API again

Key improvements:

  • Multiple tool calls per response: Model can request several tools at once
  • Explicit step types: No more message role gymnastics
  • Better structured: function_call_output vs cramming into user messages
  • Clearer semantics: Steps are first-class, not message metadata

Still your responsibility:

  • Executing the tools
  • Deciding when to stop the loop
  • Managing conversation history

API

OpenAIAdapter

interface OpenAIAdapterOptions {
  apiKey: string;
  model: string;
  structuredOutput?: {
    type: "json_schema";
    name: string;
    description?: string;
    schema: Record<string, any>;
    strict?: boolean;
  };
  reasoning?: Reasoning; // SDK type: { effort?: ReasoningEffort; summary?: "auto" | "concise" | "detailed" }
  verbosity?: "low" | "medium" | "high"; // SDK ResponseTextConfig["verbosity"]
  debug?: boolean;
}

class OpenAIAdapter implements LLMAdapter {
  constructor(options: OpenAIAdapterOptions);
  constructor(apiKey: string, model: string); // Legacy
}

Parameters

  • apiKey: Your OpenAI API key
  • model: The OpenAI model to use (e.g., "gpt-6-luna", "gpt-5.6", "o4-mini")
  • structuredOutput: Optional JSON schema for structured outputs
  • reasoning: Optional reasoning configuration, sent verbatim as reasoning
  • verbosity: Optional output verbosity, sent as text.verbosity
  • debug: Optional debug logging (default false)

Architecture Notes

Responses API vs Chat Completions

This adapter uses OpenAI's Responses API, which differs from Chat Completions in several ways:

Request Format:

  • Chat Completions: messages array with system/user/assistant roles
  • Responses API: input array with typed items (messages, function_call_outputs, etc.) + separate instructions field

Response Format:

  • Chat Completions: choices[0].message.content
  • Responses API: output array of items with type message, function_call, etc.

Tool/Function Format:

  • Chat Completions: Externally-tagged { type: "function", function: {...} }
  • Responses API: Internally-tagged { type: "function", name: "...", ... } (strict by default)

Structured Outputs:

  • Chat Completions: response_format: { type: "json_schema", json_schema: {...} }
  • Responses API: text: { format: { type: "json_schema", ... } }

The adapter seamlessly integrates with Flink's LLMAdapter interface:

  • Flink's instructions → Responses API instructions
  • Flink's messages → Converted to Responses API input items (typed steps)
  • Flink's tool schema → Converted to Responses API function format (internally-tagged, strict by default)
  • Responses output → Extracted to Flink's LLMResponse format

Each API call is one turn:

  • Flink calls adapter.execute() → One Responses API request
  • Response may contain multiple tool calls (as separate items)
  • Flink's AgentRunner executes those tools
  • Flink calls adapter.execute() again with tool results → Another Responses API request
  • Repeat until no more tool calls

This is the standard agent loop architecture used by modern frameworks (LangGraph, Vercel AI SDK, etc.)

Migration from Chat Completions

If you're coming from the Chat Completions API, the good news is: no code changes needed!

The adapter handles all the differences internally:

// This works the same way with both APIs
const app = new FlinkApp({
  ai: {
    llms: {
      default: new OpenAIAdapter({
        apiKey: process.env.OPENAI_API_KEY!,
        model: "gpt-5" // Just update the model
      }),
    },
  },
});

Benefits of upgrading:

  • ✅ Step-aware reasoning (multiple tool calls per response)
  • ✅ Better performance (3-5% improvement on benchmarks)
  • ✅ First-class tool steps (cleaner than message role hacks)
  • ✅ Future-proof (new features land here first)

Requirements

  • Node.js >= 18
  • @flink-app/flink >= 1.0.0
  • openai >= 4.77.0 (with Responses API support)

License

MIT

Resources

版本与发布记录

@flink-app/openai-adapter 共发布 86 个版本,首次发布于 2026/02/10;过去 12 个月发布了 86 个版本。

版本发布日期距今
2.0.0-alpha.134latest2026/11/078 天前
2.0.0-alpha.1332026/11/069 天前
2.0.0-alpha.1322026/11/0510 天前
2.0.0-alpha.1312026/10/2818 天前
2.0.0-alpha.1302026/10/2521 天前
2.0.0-alpha.1292026/10/2521 天前

关于 @flink-app/openai-adapter 的常见问题

@flink-app/openai-adapter 是什么?

OpenAI adapter for Flink AI framework

如何安装 @flink-app/openai-adapter?

在项目目录运行 npm install @flink-app/openai-adapter,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@flink-app/flink(>=2.0.0-alpha.134)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@flink-app/openai-adapter 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@flink-app/openai-adapter 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@flink-app/openai-adapter 可以商用吗?

@flink-app/openai-adapter 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@flink-app/openai-adapter 的下载量有多少?

根据 npm 官方下载统计,@flink-app/openai-adapter 在 2026/10/15 – 2026/11/13 这 30 天内被下载 3,518 次,日均约 117 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@flink-app/openai-adapter 还在维护吗?

最新版本 2.0.0-alpha.134 发布于 2026/11/07(8 天前);至今共发布 86 个版本,其中过去 12 个月发布了 86 个;首次发布于 2026/02/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。