yao/agent/output/adapters/openai
Max 30778bbf2f Enhance internationalization support and logging in Assistant and LLM components
- Integrated i18n translations for trace logging messages in the Assistant's Stream method, improving localization for user-facing messages.
- Updated logging in the OpenAI provider and CUI writer to utilize i18n for error messages, enhancing clarity and consistency across different locales.
- Added new embedded template handling in the i18n package, allowing for more flexible message formatting with variable substitutions.
- Improved test coverage for i18n functionalities, ensuring robust handling of various translation scenarios and edge cases.
2025-11-21 11:17:49 +08:00
..
adapter.go Enhance message handling in OpenAI adapter to skip non-delta "done" messages 2025-11-17 06:22:18 +08:00
converter.go Add streaming support and message handling in DefaultStreamHandler 2025-11-15 17:40:03 +08:00
factory.go Add streaming support and message handling in DefaultStreamHandler 2025-11-15 17:40:03 +08:00
README.md Add streaming support and message handling in DefaultStreamHandler 2025-11-15 17:40:03 +08:00
types.go Remove unnecessary blank lines in multiple files for improved code readability 2025-11-15 17:56:47 +08:00
writer.go Enhance internationalization support and logging in Assistant and LLM components 2025-11-21 11:17:49 +08:00

OpenAI Adapter

OpenAI adapter converts universal DSL messages to OpenAI-compatible format.

Conversion Rules

Built-in Types (Standard)

These types are defined in output.types.go and have standardized Props structures that all adapters must support:

Message Type Constant Props Structure OpenAI Format Description
text output.TypeText TextProps delta.content Plain text or Markdown
thinking output.TypeThinking ThinkingProps delta.reasoning_content Reasoning process (o1 models)
loading output.TypeLoading LoadingProps delta.reasoning_content Loading indicator (shows as thinking)
tool_call output.TypeToolCall ToolCallProps delta.tool_calls Tool/function calls
error output.TypeError ErrorProps error Error messages
action output.TypeAction ActionProps (not sent) System actions (silent)

Custom Types

All other message types (not in the built-in list) are converted to Markdown links:

Format Example
delta.content (link) "🖼️ [View Image](https://...)

Usage

Basic Usage

import (
    "github.com/yaoapp/yao/agent/output/adapters/openai"
)

// Create adapter with default config
adapter := openai.NewAdapter()

// Convert message
chunks, err := adapter.Adapt(msg)

With Custom Configuration

// Create adapter with options
adapter := openai.NewAdapter(
    openai.WithBaseURL("https://api.example.com"),
    openai.WithModel("gpt-4"),
    openai.WithLinkTemplate("image", "🖼️ [View Image](%s)"),
    openai.WithLinkTransformer(myOTPTransformer),
)
// Define OTP transformer
func otpTransformer(url string, msgType string, msgID string) (string, error) {
    // Generate OTP token
    otp := generateOTP(msgID, 3600) // 1 hour expiry

    // Create short link with OTP
    shortURL := fmt.Sprintf("https://api.example.com/s/%s?t=%s", msgID, otp)

    return shortURL, nil
}

// Use transformer
adapter := openai.NewAdapter(
    openai.WithLinkTransformer(otpTransformer),
)

Custom Converter

// Register custom converter for a specific type
adapter := openai.NewAdapter(
    openai.WithConverter("my_widget", func(msg *output.Message, config *openai.AdapterConfig) ([]interface{}, error) {
        // Custom conversion logic
        return []interface{}{
            // OpenAI format chunk
        }, nil
    }),
)

Examples

Text Message (Built-in Type)

Input (DSL):

{
  "type": "text",
  "props": {
    "content": "Hello world"
  }
}

Or using helper:

msg := output.NewTextMessage("Hello world")

Output (OpenAI):

{
  "id": "M1",
  "object": "chat.completion.chunk",
  "model": "yao-agent",
  "choices": [
    {
      "delta": {
        "content": "Hello world"
      }
    }
  ]
}

Image Message

Input (DSL):

{
  "id": "M2",
  "type": "image",
  "props": {
    "url": "https://example.com/avatar.jpg"
  }
}

Output (OpenAI):

{
  "id": "M2",
  "object": "chat.completion.chunk",
  "model": "yao-agent",
  "choices": [
    {
      "delta": {
        "content": "🖼️ [View Image](https://api.example.com/s/M2?t=abc123)"
      }
    }
  ]
}

Button Message

Input (DSL):

{
  "id": "M3",
  "type": "button",
  "props": {
    "text": "Approve",
    "action": "workflow.approve"
  }
}

Output (OpenAI):

{
  "id": "M3",
  "object": "chat.completion.chunk",
  "model": "yao-agent",
  "choices": [
    {
      "delta": {
        "content": "🔘 [Approve](https://api.example.com/s/M3?t=abc123)"
      }
    }
  ]
}

Default templates:

"image":  "🖼️ [View Image](%s)"
"audio":  "🔊 [Play Audio](%s)"
"video":  "🎬 [Watch Video](%s)"
"file":   "📎 [Download File](%s)"
"page":   "📄 [Open Page](%s)"
"table":  "📊 [View Table](%s)"
"chart":  "📈 [View Chart](%s)"
"list":   "📋 [View List](%s)"
"form":   "📝 [Fill Form](%s)"
"button": "🔘 [%s](%s)" // Special: button text + link

Customize templates:

adapter := openai.NewAdapter(
    openai.WithLinkTemplate("image", "📷 Image: %s"),
    openai.WithLinkTemplate("video", "🎥 Watch: %s"),
)

The link transformer is currently left empty for future implementation of OTP/short link functionality.

Planned features:

  • Generate one-time password (OTP) for secure access
  • Create short URLs for better readability
  • Set expiration time for links
  • Track link access for analytics

Example implementation:

func otpTransformer(url string, msgType string, msgID string) (string, error) {
    // TODO: Implement OTP generation
    // 1. Generate OTP token with expiry
    // 2. Store mapping: token -> (url, msgType, msgID, expiry)
    // 3. Create short URL with token
    // 4. Return short URL

    return url, nil // Currently pass-through
}