goim

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 8, 2026 License: MIT Imports: 25 Imported by: 0

README

goim

A platform-agnostic IM gateway library for Go. Connect any AI agent backend to 10+ chat platforms through a single Runtime interface.

中文文档

Features

  • Single interface integration — implement Runtime to bridge your agent to all supported platforms
  • 10 IM platforms — Telegram, Feishu (Lark), Discord, Slack, DingTalk, WeCom, QQ, QQBot, LINE, WeChat
  • Streaming support — real-time text, tool use, and error events via channel-based API
  • Multi-channel config — manage multiple platform credentials in a single channels.json
  • Session management — per-user sessions with concurrent message handling
  • Rotating log — automatic log rotation with size-based pruning

Install

go get github.com/godeps/goim@latest

Quick Start

1. Implement the Runtime interface
package main

import (
    "context"
    "github.com/godeps/goim"
)

type MyRuntime struct{}

func (r *MyRuntime) RunStream(ctx context.Context, req goim.Request) (<-chan goim.StreamEvent, error) {
    ch := make(chan goim.StreamEvent, 16)
    go func() {
        defer close(ch)
        // Process req.Prompt, stream back events
        ch <- goim.StreamEvent{
            Type:  goim.EventContentBlockDelta,
            Delta: &goim.Delta{Text: "Hello from my agent!"},
        }
        ch <- goim.StreamEvent{Type: goim.EventMessageStop}
    }()
    return ch, nil
}
2. Start the gateway
func main() {
    rt := &MyRuntime{}
    cfg := goim.ConfigFromFlags("telegram", "YOUR_BOT_TOKEN", "")

    platforms, _ := goim.CreatePlatforms(cfg)
    agent := goim.NewAgent(rt, "mybot")
    engine := goim.NewEngine(agent, platforms, cfg)

    engine.Start()
    // Block until interrupted...
}
3. Or use the controller for lifecycle management
ctrl := goim.NewIMController("/path/to/channels.json")
err := ctrl.Start(rt, "mybot", "telegram", "YOUR_BOT_TOKEN", "", "")
// ...
ctrl.Stop()

Configuration

channels.json

Manage multiple platforms in a single file:

{
  "channels": {
    "telegram": {
      "token": "123456:ABC-DEF",
      "enabled": true
    },
    "feishu": {
      "app_id": "cli_xxx",
      "app_secret": "secret",
      "enabled": true
    },
    "discord": {
      "token": "discord-bot-token",
      "enabled": false
    }
  },
  "language": "zh"
}
Platform credentials
Platform Required fields
Telegram token
Feishu app_id, app_secret
Discord token
Slack bot_token, app_token
DingTalk client_id, client_secret
WeCom corp_id, corp_secret, agent_id
QQ ws_url (optional)
QQBot app_id, app_secret
LINE channel_secret, channel_token
WeChat token
TOML config (legacy)
[project]
name = "mybot"

[[project.platforms]]
type = "telegram"
[project.platforms.options]
token = "YOUR_BOT_TOKEN"

Stream Events

Constant Description
EventContentBlockDelta Incremental text output
EventToolExecutionStart Tool call started
EventToolExecutionResult Tool call completed
EventToolExecutionOutput Intermediate tool output
EventError Error occurred
EventMessageStop Message generation finished

License

MIT


中文文档

goim 是一个平台无关的 Go 语言 IM 网关库。通过实现一个 Runtime 接口,即可将任意 AI Agent 后端接入 10+ 聊天平台。

特性

  • 单接口集成 — 实现 Runtime 接口即可桥接所有支持的平台
  • 10 个 IM 平台 — Telegram、飞书、Discord、Slack、钉钉、企业微信、QQ、QQ 机器人、LINE、微信
  • 流式支持 — 基于 channel 的实时文本、工具调用和错误事件流
  • 多渠道配置 — 通过 channels.json 统一管理多平台凭据
  • 会话管理 — 按用户隔离会话,支持并发消息处理
  • 日志轮转 — 按大小自动轮转日志文件

安装

go get github.com/godeps/goim@latest

快速开始

1. 实现 Runtime 接口
package main

import (
    "context"
    "github.com/godeps/goim"
)

type MyRuntime struct{}

func (r *MyRuntime) RunStream(ctx context.Context, req goim.Request) (<-chan goim.StreamEvent, error) {
    ch := make(chan goim.StreamEvent, 16)
    go func() {
        defer close(ch)
        // 处理 req.Prompt,流式返回事件
        ch <- goim.StreamEvent{
            Type:  goim.EventContentBlockDelta,
            Delta: &goim.Delta{Text: "你好!"},
        }
        ch <- goim.StreamEvent{Type: goim.EventMessageStop}
    }()
    return ch, nil
}
2. 启动网关
func main() {
    rt := &MyRuntime{}
    cfg := goim.ConfigFromFlags("telegram", "你的机器人Token", "")

    platforms, _ := goim.CreatePlatforms(cfg)
    agent := goim.NewAgent(rt, "mybot")
    engine := goim.NewEngine(agent, platforms, cfg)

    engine.Start()
    // 阻塞等待中断信号...
}
3. 使用 Controller 管理生命周期
ctrl := goim.NewIMController("/path/to/channels.json")
err := ctrl.Start(rt, "mybot", "telegram", "你的Token", "", "")
// ...
ctrl.Stop()

配置

channels.json

通过一个文件管理多个平台:

{
  "channels": {
    "telegram": {
      "token": "123456:ABC-DEF",
      "enabled": true
    },
    "feishu": {
      "app_id": "cli_xxx",
      "app_secret": "secret",
      "enabled": true
    }
  },
  "language": "zh"
}
各平台所需凭据
平台 必需字段
Telegram token
飞书 app_id, app_secret
Discord token
Slack bot_token, app_token
钉钉 client_id, client_secret
企业微信 corp_id, corp_secret, agent_id
QQ ws_url(可选)
QQ 机器人 app_id, app_secret
LINE channel_secret, channel_token
微信 token

流式事件类型

常量 说明
EventContentBlockDelta 增量文本输出
EventToolExecutionStart 工具调用开始
EventToolExecutionResult 工具调用完成
EventToolExecutionOutput 工具中间输出
EventError 发生错误
EventMessageStop 消息生成完毕

许可证

MIT

Documentation

Overview

Package goim provides a platform-agnostic IM gateway that bridges any Runtime (agent backend) to multiple chat platforms via cc-connect.

Index

Constants

View Source
const (
	EventContentBlockDelta   = "content_block_delta"
	EventToolExecutionStart  = "tool_execution_start"
	EventToolExecutionResult = "tool_execution_result"
	EventToolExecutionOutput = "tool_execution_output"
	EventError               = "error"
	EventMessageStop         = "message_stop"
)

Stream event type constants.

Variables

This section is empty.

Functions

func CreatePlatforms

func CreatePlatforms(cfg Config) ([]core.Platform, error)

CreatePlatforms instantiates cc-connect Platform objects from config.

func ResolveDataDir

func ResolveDataDir(cfg Config) string

ResolveDataDir returns the data directory, defaulting to .animus/connect.

func ResolveLang

func ResolveLang(lang string) core.Language

ResolveLang converts a language string to a cc-connect Language constant.

func SaveChannelsJSON

func SaveChannelsJSON(path string, cfg ChannelsConfig) error

SaveChannelsJSON writes the channels config to a JSON file, creating parent directories as needed.

func SetupIMLogger

func SetupIMLogger() (cleanup func(), err error)

SetupIMLogger configures slog to write IM bridge logs to rotated JSON files under ~/.animus/logs/. Logs are NOT written to the terminal. Returns a cleanup function that restores the original slog handler and closes the log file.

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent implements core.Agent by wrapping a Runtime.

func NewAgent

func NewAgent(rt Runtime, name string) *Agent

NewAgent creates a new Agent adapter around an existing Runtime.

func (*Agent) ListSessions

func (a *Agent) ListSessions(_ context.Context) ([]core.AgentSessionInfo, error)

func (*Agent) Name

func (a *Agent) Name() string

func (*Agent) StartSession

func (a *Agent) StartSession(ctx context.Context, sessionID string) (core.AgentSession, error)

func (*Agent) Stop

func (a *Agent) Stop() error

type ChannelsConfig

type ChannelsConfig struct {
	Channels      map[string]map[string]any `json:"channels"`
	Language      string                    `json:"language,omitempty"`
	StreamPreview *StreamPreviewJSON        `json:"stream_preview,omitempty"`
}

ChannelsConfig is the JSON-native config format stored in ~/.animus/channels.json (user-global). Each key in Channels is a platform name (e.g. "telegram", "feishu") and the value is passed directly to core.CreatePlatform as options.

func LoadChannelsJSON

func LoadChannelsJSON(path string) (ChannelsConfig, error)

LoadChannelsJSON reads a channels.json file. Returns an empty config (not an error) if the file does not exist.

func (ChannelsConfig) LookupChannel

func (c ChannelsConfig) LookupChannel(platform string) map[string]any

LookupChannel returns the options for a specific channel from a ChannelsConfig. Returns nil if the channel is not found or is disabled.

func (ChannelsConfig) ToConfig

func (c ChannelsConfig) ToConfig() Config

ToConfig converts a ChannelsConfig to the internal Config format used by CreatePlatforms. Channels with enabled=false are skipped.

type Config

type Config struct {
	DataDir       string              `toml:"data_dir"`
	Language      string              `toml:"language"`
	Log           LogConfig           `toml:"log"`
	StreamPreview StreamPreviewConfig `toml:"stream_preview"`
	Project       ProjectConfig       `toml:"project"`
}

Config is a simplified subset of cc-connect's config.toml focused on the fields needed to run an IM bridge.

func ConfigFromFlags

func ConfigFromFlags(platform, token, allowFrom string) Config

ConfigFromFlags builds a minimal Config from CLI flags for the common case of a single platform without a config file.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns sensible defaults.

func LoadConfig

func LoadConfig(path string) (Config, error)

LoadConfig reads a config file. Returns defaults if path is empty.

type ContentBlock

type ContentBlock struct {
	Type      string // e.g. "image"
	MediaType string // e.g. "image/png"
	Data      string // base64-encoded data
}

ContentBlock carries multimodal content (e.g., images).

type Delta

type Delta struct {
	Type string // e.g. "text_delta"
	Text string
}

Delta carries incremental text content.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine wraps cc-connect's core.Engine with goim-specific configuration.

func NewEngine

func NewEngine(agent *Agent, platforms []core.Platform, cfg Config) *Engine

NewEngine creates a cc-connect Engine binding the given Agent adapter and Platforms.

func (*Engine) Start

func (e *Engine) Start() error

Start starts all platforms and begins routing messages.

func (*Engine) Stop

func (e *Engine) Stop() error

Stop gracefully shuts down all platforms and the agent.

type IMController

type IMController struct {
	ChannelsPath string // path to ~/.animus/channels.json
	// contains filtered or unexported fields
}

IMController manages the lifecycle of an IM bridge Engine.

func NewIMController

func NewIMController(channelsPath string) *IMController

NewIMController creates a new controller with no active bridge. channelsPath is the path to ~/.animus/channels.json for auto-load/save.

func (*IMController) DeleteChannel

func (c *IMController) DeleteChannel(platform string) error

DeleteChannel removes a platform from channels.json.

func (*IMController) Running

func (c *IMController) Running() bool

Running reports whether the bridge is active.

func (*IMController) SaveChannel

func (c *IMController) SaveChannel(platform string, opts map[string]any) error

SaveChannel persists a platform's credentials to channels.json.

func (*IMController) Start

func (c *IMController) Start(runtime Runtime, name, platform, token, allowFrom, configPath string) error

Start launches the IM bridge. If already running, returns an error.

Priority for resolving configuration:

  1. platform + token provided directly (dialog mode) -> use immediately
  2. platform provided without token -> look up saved config in channels.json
  3. configPath non-empty -> load TOML config (legacy compatibility)
  4. no platform -> load all enabled channels from channels.json

func (*IMController) StartWithOpts

func (c *IMController) StartWithOpts(runtime Runtime, name, platform string, opts map[string]any) error

StartWithOpts launches the IM bridge using raw platform options (from tool credentials).

func (*IMController) Status

func (c *IMController) Status() string

Status returns a human-readable status string.

func (*IMController) Stop

func (c *IMController) Stop() error

Stop shuts down the IM bridge. No-op if not running.

type LogConfig

type LogConfig struct {
	Level string `toml:"level"`
}

type PlatformConfig

type PlatformConfig struct {
	Type    string         `toml:"type"`
	Options map[string]any `toml:"options"`
}

type ProjectConfig

type ProjectConfig struct {
	Name      string           `toml:"name"`
	Platforms []PlatformConfig `toml:"platforms"`
}

type Request

type Request struct {
	Prompt        string
	SessionID     string
	ContentBlocks []ContentBlock
}

Request represents a user message forwarded from an IM platform.

type Runtime

type Runtime interface {
	RunStream(ctx context.Context, req Request) (<-chan StreamEvent, error)
}

Runtime is the interface that host applications must implement to integrate with goim. It receives user messages from IM platforms and streams back responses.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session implements core.AgentSession by calling Runtime.RunStream for each user message and converting StreamEvent to core.Event.

func (*Session) Alive

func (s *Session) Alive() bool

func (*Session) Close

func (s *Session) Close() error

func (*Session) CurrentSessionID

func (s *Session) CurrentSessionID() string

func (*Session) Events

func (s *Session) Events() <-chan core.Event

func (*Session) RespondPermission

func (s *Session) RespondPermission(_ string, _ core.PermissionResult) error

func (*Session) Send

func (s *Session) Send(prompt string, images []core.ImageAttachment, files []core.FileAttachment) error

type StreamEvent

type StreamEvent struct {
	Type      string
	Name      string      // tool name (for tool events)
	Delta     *Delta      // text delta (for content events)
	Output    interface{} // tool output or error message
	SessionID string
}

StreamEvent is a single event in a streaming response.

type StreamPreviewConfig

type StreamPreviewConfig struct {
	Enabled       *bool `toml:"enabled"`
	IntervalMs    *int  `toml:"interval_ms"`
	MinDeltaChars *int  `toml:"min_delta_chars"`
	MaxChars      *int  `toml:"max_chars"`
}

func (StreamPreviewConfig) ToStreamPreviewCfg

func (sp StreamPreviewConfig) ToStreamPreviewCfg() core.StreamPreviewCfg

ToStreamPreviewCfg converts to cc-connect's core.StreamPreviewCfg.

type StreamPreviewJSON

type StreamPreviewJSON struct {
	Enabled       *bool `json:"enabled,omitempty"`
	IntervalMs    *int  `json:"interval_ms,omitempty"`
	MinDeltaChars *int  `json:"min_delta_chars,omitempty"`
	MaxChars      *int  `json:"max_chars,omitempty"`
}

StreamPreviewJSON is the JSON variant of StreamPreviewConfig.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL