tim-api

command module
v0.0.0-...-7ad5d0e Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2026 License: MIT Imports: 1 Imported by: 0

README

Tim API Server

A production-ready Go server framework that combines multiple gRPC services with REST APIs using Connect-Go and Vanguard-Go. Built with Buf for efficient Protocol Buffer management.

Features

  • Dual Server Architecture: Runs two HTTP servers in a single binary
    • External Server (port 3000): Public-facing API with authentication and authorization
    • Internal Server (port 3001): Internal APIs for worker communication (no auth)
  • Multi-Protocol Support: Serves both gRPC and REST APIs from the same service definitions
    • Connect-Go Framework: Modern, type-safe RPC framework with excellent Go support
    • REST Gateway: Automatic REST API generation from gRPC services using Vanguard and google.api.http annotations in proto files
    • OpenAPI Support: Auto-generated OpenAPI (Swagger) documentation
    • Protovalidate: Request validation using buf.build/protovalidate
  • Authentication: Middleware for AuthN with Stytch
  • Service Architecture: Modular design with multiple services (User, Persona, Thread, Todo)
  • Streaming Support: Real-time streaming for messages and task updates
  • Docker Support: Containerized deployment with multi-stage builds

Architecture

tim-api/
├── cmd/server/         # Server entry point
├── internal/           # Internal packages
│   ├── config/         # Configuration management
│   ├── middleware/     # HTTP and RPC interceptors
│   ├── server/         # Server setup and routing
│   └── services/       # Service implementations
│       ├── user/       # User service
│       └── session/    # Session service
├── pkg/                # Public packages
│   ├── logger/         # Structured logging
│   └── errors/         # Error handling
├── proto/              # Protocol buffer definitions
│   ├── user/v1/        # User service protos
│   ├── session/v1/     # Session service protos
│   └── common/v1/     # Shared types
└── gen/                # Generated code (git-ignored)

Services

User Service
  • User CRUD operations
  • Authentication and profile management
  • RESTful endpoints at /api/v1/users/
Session Service
  • Session management for conversations
  • Real-time message streaming
  • RESTful endpoints at /api/v1/sessions/

Quick Start

Prerequisites
  • Go 1.23 or later
  • Make
  • Docker (optional)
Development
  1. Generate autogen go code:
just builder::gen
  1. Build the server:
just builder::build-tim-api
  1. Run the server:
./build/tim-api

The server will start two HTTP servers:

  • External API: http://localhost:3000 (public-facing with auth)
  • Internal API: http://localhost:3001 (worker communication, no auth)
Configuration

The service follows the 12-factor app principle and uses environment variables for all configuration. Copy the example environment file:

cp .env.example .env

Available environment variables:

External Server (Public API)

  • EXTERNAL_SERVER_ADDR - External server address (default: 127.0.0.1)
  • EXTERNAL_PORT - External server port (default: 3000)
  • CORS_ENABLED - Enable CORS for external API (default: false)
  • CORS_ORIGINS - Comma-separated list of allowed origins (default: *)

Internal Server (Worker Communication)

  • INTERNAL_SERVER_ADDR - Internal server address (default: 127.0.0.1)
  • INTERNAL_PORT - Internal server port (default: 3001)

General

  • DEV_MODE - Enable development mode (default: true)
  • LOG_LEVEL - Logging level: trace, debug, info, error (default: debug)
  • LOG_FORMAT - Log format: json or console (default: json)

Authentication

  • AUTHN_ENABLED - Enable authentication (default: false)
  • AUTHN_TYPE - Authentication type: jwt (default: jwt)
  • AUTHN_STYTCH_PROJECT_ID - Stytch project ID
  • AUTHN_STYTCH_SECRET - Stytch secret

Authorization

  • AUTHZ_ENABLED - Enable authorization (default: false)
  • AUTHZ_CERBOS_PATH - Cerbos service URL

Database

  • DATABASE_TYPE - Database type: postgres (default: postgres)
  • DATABASE_URL - Database connection string
Testing

Run tests:

just testing::test_tim_api

Run tests with coverage:

just testing::test_tim_api true

API Examples

gRPC (using Connect-Go client)
import (
    "connectrpc.com/connect"
    userv1 "github.com/greylabs/tim-api/gen/user/v1"
    "github.com/greylabs/tim-api/gen/user/v1/userv1connect"
)

client := userv1connect.NewUserServiceClient(
    http.DefaultClient,
    "http://localhost:8080",
)

resp, err := client.CreateUser(context.Background(), 
    connect.NewRequest(&userv1.CreateUserRequest{
        Email: "user@example.com",
        Name:  "John Doe",
    }),
)
REST API

The REST API routes are defined using HTTP annotations in the proto files:

# Create a user
curl -X POST http://localhost:8080/v1/users \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "name": "John Doe",
    "password": "secure_password"
  }'

# Get a specific user
curl http://localhost:8080/v1/users/{user_id}

# Update a user (PATCH)
curl -X PATCH http://localhost:8080/v1/users/{user_id} \
  -H "Content-Type: application/json" \
  -d '{
    "user": {
      "name": "Jane Doe"
    },
    "update_mask": {
      "paths": ["name"]
    }
  }'

# Delete a user
curl -X DELETE http://localhost:8080/v1/users/{user_id}

# Create a session
curl -X POST http://localhost:8080/v1/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_123",
    "name": "My Session",
    "type": "SESSION_TYPE_INTERACTIVE"
  }'

# List all sessions
curl http://localhost:8080/v1/sessions

# List user's sessions (alternative route)
curl http://localhost:8080/v1/users/{user_id}/sessions

# Send a message
curl -X POST http://localhost:8080/v1/sessions/{session_id}/messages \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Hello, Tim!",
    "role": "MESSAGE_ROLE_USER"
  }'

# Get messages from a session
curl http://localhost:8080/v1/sessions/{session_id}/messages

# Stream messages (Server-Sent Events)
curl http://localhost:8080/v1/sessions/{session_id}/messages:stream

# Execute a task with an agent
curl -X POST http://localhost:8080/v1/agents/{agent_id}/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "session_123",
    "description": "Generate a hello world program",
    "input": {
      "language": "go"
    }
  }'

# Stream task updates (Server-Sent Events)
curl http://localhost:8080/v1/tasks/{task_id}:stream
HTTP Annotations

The REST API routes are defined using google.api.http annotations in the proto files. For example:

service UserService {
  rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) {
    option (google.api.http) = {
      post: "/v1/users"
      body: "*"
    };
  }
  
  rpc GetUser(GetUserRequest) returns (GetUserResponse) {
    option (google.api.http) = {
      get: "/v1/users/{id}"
    };
  }
}

This provides:

  • Custom REST paths independent of RPC service names
  • Support for path parameters (e.g., {id})
  • Multiple HTTP bindings for the same RPC method
  • RESTful conventions (GET, POST, PATCH, DELETE)
  • Custom actions using : notation (e.g., :stream)

Docker Deployment

Build the Docker image:

make docker-build

Run the container:

make docker-run

Development Tools

Linting

Run linters:

just lint
Formatting

Format code:

just format

Adding New Services

  1. Define your service in proto/<service>/v1/<service>.proto
  2. Run just builder::proto to generate code
  3. Implement the service in internal/services/<service>/
  4. Register in internal/services/registry.go
  5. Mount in internal/server/server.go

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

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