first commit
This commit is contained in:
72
docs/contributing/adding-a-configstore.mdx
Normal file
72
docs/contributing/adding-a-configstore.mdx
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: "Adding config store"
|
||||
description: "Learn how to contribute a backend for the config store in Bifrost"
|
||||
icon: "database"
|
||||
---
|
||||
|
||||
The Config store in Bifrost is designed to be extensible, allowing support for different database backends. This guide outlines the philosophy, architecture, and steps to add support for a new database.
|
||||
|
||||
This guide will help you add a new custom backend for the config store. Currently, bifrost supports PostgreSQL and SQLite.
|
||||
|
||||
## Setup
|
||||
|
||||
We assume you have some idea about how Bifrost works and you have already [set up bifrost for local development](./setting-up-repo).
|
||||
|
||||
## Architecture
|
||||
|
||||
The system is built around a few key components:
|
||||
|
||||
1. **`ConfigStore` Interface**: This is the heart of the system. It defines all the methods required to read and write configuration data (e.g., `GetClientConfig`, `UpdateProvider`). Any valid store must implement this interface.
|
||||
2. **`RDBConfigStore`**: A reusable implementation for Relational Databases (RDBs). It uses an ORM (GORM) to map the interface methods to SQL queries. If your target database is supported by GORM, you can likely reuse this implementation entirely.
|
||||
3. **Configuration Structs**: Each database type has its own configuration struct (e.g., `SQLiteConfig`, `PostgresConfig`) that defines how to connect to it.
|
||||
|
||||
## Config store structure
|
||||
|
||||
The config store is used to save all your bifrost configurations. This can be a simple in-memory store or a postgres database. Bifrost exposes a single interface (ConfigStore) for all configuration CRUD (Create, Read, Update, Delete) operations.
|
||||
|
||||
Any custom backend for config store should implement the `ConfigStore` interface. The interface is defined in [configstore/store.go](https://github.com/maximhq/bifrost/blob/main/framework/configstore/store.go).
|
||||
|
||||
## Using GORM
|
||||
|
||||
It is recommended to use GORM for the config store. GORM is a popular ORM (Object-Relational Mapping) library for Go. It provides a simple and efficient way to interact with databases.
|
||||
|
||||
GORM provides implementations for the functions listed in the `ConfigStore` interface. This significantly simplifies the implementation of the config store (see [postgres.go](https://github.com/maximhq/bifrost/blob/main/framework/configstore/postgres.go) as an example).
|
||||
|
||||
## Conventions
|
||||
|
||||
When adding a new database, please follow these conventions:
|
||||
|
||||
### File Placement
|
||||
* The main interface and factory method are in `framework/configstore/store.go`.
|
||||
* Shared RDB implementation details are in `framework/configstore/rdb.go`.
|
||||
* Create a new file for your database implementation, named after the database (e.g., `framework/configstore/postgres.go`).
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
1. Add a new constant to the `ConfigStoreType` in `store.go`.
|
||||
2. Define a struct in your new database file that contains all connection parameters (host, port, credentials, etc.).
|
||||
3. Implement the Factory Function: Create a function that:
|
||||
* Accepts the configuration struct and a logger
|
||||
* Opens a GORM database connection using your database's GORM driver
|
||||
* Returns an instance of `RDBConfigStore` with the database connection
|
||||
* Runs migrations to ensure the schema is up-to-date
|
||||
4. Update the Factory: Add a new case in the `NewConfigStore` function in `store.go` to handle your new database type.
|
||||
5. If needed, update the `Config` struct's `UnmarshalJSON` method in `config.go` to properly parse your configuration.
|
||||
|
||||
### Error Handling
|
||||
|
||||
Make sure to properly handle errors during:
|
||||
* Database connection establishment
|
||||
* Migration execution
|
||||
* Connection cleanup (especially important if migrations fail)
|
||||
|
||||
### Testing Considerations
|
||||
|
||||
* Ensure your implementation can handle concurrent access to the database
|
||||
* Consider connection pooling and timeout settings appropriate for your database
|
||||
* Test with both empty and populated databases
|
||||
* Verify that all `ConfigStore` interface methods work correctly with your backend
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help, please reach out to the Bifrost team on [Discord](https://discord.gg/exN5KAydbU).
|
||||
77
docs/contributing/adding-a-logstore.mdx
Normal file
77
docs/contributing/adding-a-logstore.mdx
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: "Adding a log store"
|
||||
description: "Learn how to contribute a backend for the log store in Bifrost"
|
||||
icon: "database"
|
||||
---
|
||||
|
||||
The Log store in Bifrost is designed to be extensible, allowing support for different database backends. This guide outlines the philosophy, architecture, and steps to add support for a new database.
|
||||
|
||||
This guide will help you add a new custom backend for the log store. Currently, Bifrost supports PostgreSQL and SQLite.
|
||||
|
||||
## Setup
|
||||
|
||||
We assume you have some idea about how Bifrost works and you have already [set up bifrost for local development](./setting-up-repo).
|
||||
|
||||
## Architecture
|
||||
|
||||
The system is built around a few key components:
|
||||
|
||||
1. **`LogStore` Interface**: This is the heart of the system. It defines all the methods required to create, read, search, and manage log entries (e.g., `Create`, `SearchLogs`, `GetStats`, `Flush`). Any valid store must implement this interface.
|
||||
2. **`RDBLogStore`**: A reusable implementation for Relational Databases (RDBs). It uses an ORM (GORM) to map the interface methods to SQL queries. If your target database is supported by GORM, you can likely reuse this implementation entirely.
|
||||
3. **Configuration Structs**: Each database type has its own configuration struct (e.g., `SQLiteConfig`, `PostgresConfig`) that defines how to connect to it.
|
||||
|
||||
## Log store structure
|
||||
|
||||
The log store is used to persist all request/response logs from your Bifrost proxy. This can be a lightweight SQLite database or a production-grade Postgres database. Bifrost exposes a single interface (`LogStore`) for all logging operations.
|
||||
|
||||
Any custom backend for log store should implement the `LogStore` interface. The interface is defined in [logstore/store.go](https://github.com/maximhq/bifrost/blob/main/framework/logstore/store.go).
|
||||
|
||||
## Using GORM
|
||||
|
||||
It is recommended to use GORM for the log store. GORM is a popular ORM (Object-Relational Mapping) library for Go. It provides a simple and efficient way to interact with databases.
|
||||
|
||||
GORM provides implementations for the functions listed in the `LogStore` interface. This significantly simplifies the implementation of the log store (see [postgres.go](https://github.com/maximhq/bifrost/blob/main/framework/logstore/postgres.go) as an example).
|
||||
|
||||
## Conventions
|
||||
|
||||
When adding a new database, please follow these conventions:
|
||||
|
||||
### File Placement
|
||||
* The main interface and factory method are in `framework/logstore/store.go`.
|
||||
* Shared RDB implementation details are in `framework/logstore/rdb.go`.
|
||||
* Create a new file for your database implementation, named after the database (e.g., `framework/logstore/postgres.go`).
|
||||
|
||||
### Naming Conventions
|
||||
* Define a constant for your database type in `store.go` following the pattern `LogStoreType[DatabaseName]` (e.g., `LogStoreTypePostgres`).
|
||||
* Name your config struct as `[DatabaseName]Config` (e.g., `PostgresConfig`).
|
||||
* Name your constructor function as `new[DatabaseName]LogStore` (e.g., `newPostgresLogStore`).
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
1. Add a new constant to the `LogStoreType` in `store.go`.
|
||||
2. Define a struct in your new database file that contains all connection parameters (host, port, credentials, etc.).
|
||||
3. Create a function that:
|
||||
* Accepts the configuration struct and a logger
|
||||
* Opens a GORM database connection using your database's GORM driver
|
||||
* Returns an instance of `RDBLogStore` with the database connection
|
||||
* Runs migrations to ensure the schema is up-to-date
|
||||
4. Add a new case in the `NewLogStore` function in `store.go` to handle your new database type.
|
||||
5. If needed, update the `Config` struct's `UnmarshalJSON` method in `config.go` to properly parse your configuration.
|
||||
|
||||
### Error Handling
|
||||
|
||||
Make sure to properly handle errors during:
|
||||
* Database connection establishment
|
||||
* Migration execution
|
||||
* Connection cleanup (especially important if migrations fail)
|
||||
|
||||
### Testing Considerations
|
||||
|
||||
* Ensure your implementation can handle concurrent access to the database
|
||||
* Consider connection pooling and timeout settings appropriate for your database
|
||||
* Test with both empty and populated databases
|
||||
* Verify that all `LogStore` interface methods work correctly with your backend
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help, please reach out to the Bifrost team on [Discord](https://discord.gg/exN5KAydbU).
|
||||
0
docs/contributing/adding-a-plugin.mdx
Normal file
0
docs/contributing/adding-a-plugin.mdx
Normal file
2353
docs/contributing/adding-a-provider.mdx
Normal file
2353
docs/contributing/adding-a-provider.mdx
Normal file
File diff suppressed because it is too large
Load Diff
114
docs/contributing/adding-a-vectorstore.mdx
Normal file
114
docs/contributing/adding-a-vectorstore.mdx
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: "Adding a vector store"
|
||||
description: "Learn how to contribute a backend for the vector store in Bifrost"
|
||||
icon: "circle-nodes"
|
||||
---
|
||||
|
||||
The Vector store in Bifrost is designed to be extensible, allowing support for different vector database backends. This guide outlines the philosophy, architecture, and steps to add support for a new vector database.
|
||||
|
||||
This guide will help you add a new custom backend for the vector store. Currently, Bifrost supports Weaviate, Redis and Qdrant.
|
||||
|
||||
## Setup
|
||||
|
||||
We assume you have some idea about how Bifrost works and you have already [set up bifrost for local development](./setting-up-repo).
|
||||
|
||||
## Architecture
|
||||
|
||||
The system is built around a few key components:
|
||||
|
||||
1. **`VectorStore` Interface**: This is the heart of the system. It defines all the methods required for vector operations including namespace management, similarity search, CRUD operations, and filtering (e.g., `CreateNamespace`, `GetNearest`, `Add`, `Delete`). Any valid store must implement this interface.
|
||||
2. **Database-Specific Stores**: Unlike relational stores, vector databases have unique characteristics. Each implementation (e.g., `WeaviateStore`, `RedisStore`) uses the native client library for that database to provide optimal performance.
|
||||
3. **Configuration Structs**: Each database type has its own configuration struct (e.g., `WeaviateConfig`, `RedisConfig`) that defines connection details and database-specific settings.
|
||||
4. **Query Abstraction**: The `Query` type provides a common way to express filters across different backends, with each implementation translating to its native query language.
|
||||
|
||||
## Vector store structure
|
||||
|
||||
The vector store is used for semantic search and similarity matching in Bifrost. This enables features like RAG (Retrieval-Augmented Generation) and intelligent document retrieval. Bifrost exposes a single interface (`VectorStore`) for all vector operations.
|
||||
|
||||
Any custom backend for vector store should implement the `VectorStore` interface. The interface is defined in [vectorstore/store.go](https://github.com/maximhq/bifrost/blob/main/framework/vectorstore/store.go).
|
||||
|
||||
## Key interface methods
|
||||
|
||||
The `VectorStore` interface includes methods for:
|
||||
|
||||
* **Namespace Management**: Create and delete namespaces (collections/indices)
|
||||
* **Health Checks**: Ping to verify connectivity
|
||||
* **Data Operations**: Add, get, and delete vector embeddings with metadata
|
||||
* **Similarity Search**: Find nearest neighbors using vector similarity
|
||||
* **Filtering**: Query with metadata filters and pagination
|
||||
* **Batch Operations**: Retrieve or delete multiple items efficiently
|
||||
|
||||
## Using native clients
|
||||
|
||||
Unlike the config and log stores which use GORM, vector stores use native database clients. This is because:
|
||||
|
||||
* Vector databases have specialized APIs optimized for similarity search
|
||||
* Each database has unique features (e.g., Weaviate's GraphQL, Redis's vector syntax)
|
||||
* Performance is critical for vector operations
|
||||
|
||||
You should use the official Go client library for your target vector database.
|
||||
|
||||
## Conventions
|
||||
|
||||
When adding a new database, please follow these conventions:
|
||||
|
||||
### File Placement
|
||||
* The main interface and factory method are in `framework/vectorstore/store.go`.
|
||||
* Create a new file for your database implementation, named after the database (e.g., `framework/vectorstore/pinecone.go`).
|
||||
|
||||
### Naming Conventions
|
||||
* Define a constant for your database type in `store.go` following the pattern `VectorStoreType[DatabaseName]` (e.g., `VectorStoreTypeWeaviate`).
|
||||
* Name your config struct as `[DatabaseName]Config` (e.g., `WeaviateConfig`).
|
||||
* Name your store struct as `[DatabaseName]Store` (e.g., `WeaviateStore`).
|
||||
* Name your constructor function as `new[DatabaseName]Store` (e.g., `newWeaviateStore`).
|
||||
|
||||
### Implementation Steps
|
||||
|
||||
1. Add a new constant to the `VectorStoreType` in `store.go`.
|
||||
2. Define a configuration struct in your new database file that contains all connection parameters (host, API keys, timeout settings, etc.).
|
||||
3. Create a store struct that holds the database client, configuration, and logger.
|
||||
4. Implement all methods from the `VectorStore` interface:
|
||||
* Connection and health checks (`Ping`)
|
||||
* Namespace/collection management (`CreateNamespace`, `DeleteNamespace`)
|
||||
* Single and batch retrieval (`GetChunk`, `GetChunks`)
|
||||
* Filtered queries (`GetAll` with pagination)
|
||||
* Similarity search (`GetNearest`)
|
||||
* Add/update operations (`Add`)
|
||||
* Delete operations (`Delete`, `DeleteAll`)
|
||||
* Cleanup (`Close`)
|
||||
5. Implement query translation logic to convert the generic `Query` type to your database's native filter format.
|
||||
6. Create a constructor function that initializes the database client and validates connectivity.
|
||||
7. Update the `NewVectorStore` factory function in `store.go` to handle your new database type.
|
||||
8. Update the `Config` struct's `UnmarshalJSON` method in `store.go` to properly parse your configuration.
|
||||
|
||||
### Query translation
|
||||
|
||||
Each vector database has its own query syntax. You'll need to implement functions to translate the generic `Query` type to your database's format. For example:
|
||||
|
||||
* Weaviate uses GraphQL-style filters
|
||||
* Redis uses FT.SEARCH query syntax
|
||||
|
||||
Study the existing implementations (`buildWeaviateFilter`, `buildRedisQuery`) for patterns to follow.
|
||||
|
||||
### Error Handling
|
||||
|
||||
Make sure to properly handle errors during:
|
||||
* Database connection establishment
|
||||
* Client initialization and authentication
|
||||
* Query execution (especially for complex similarity searches)
|
||||
* Namespace creation and deletion
|
||||
* Connection cleanup
|
||||
|
||||
### Testing Considerations
|
||||
|
||||
* Test all `VectorStore` interface methods with your backend
|
||||
* Verify similarity search returns results in the correct order
|
||||
* Test filtering with various query operators (Equal, GreaterThan, ContainsAny, etc.)
|
||||
* Ensure pagination works correctly with cursors
|
||||
* Test batch operations with different sizes
|
||||
* Verify namespace isolation (data from one namespace doesn't leak to another)
|
||||
* Consider performance benchmarks for large-scale vector operations
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help, please reach out to the Bifrost team on [Discord](https://discord.gg/exN5KAydbU).
|
||||
358
docs/contributing/code-conventions.mdx
Normal file
358
docs/contributing/code-conventions.mdx
Normal file
@@ -0,0 +1,358 @@
|
||||
---
|
||||
title: "Code Conventions"
|
||||
description: "Code style and convention guidelines for contributing to Bifrost."
|
||||
icon: "brush"
|
||||
---
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
All commits to Bifrost should follow a standardized format. This ensures clear history and makes it easy to understand changes at a glance.
|
||||
|
||||
### Format
|
||||
|
||||
```
|
||||
[type]: description
|
||||
|
||||
Optional body with more details
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
- **feat** - New feature
|
||||
- **fix** - Bug fix
|
||||
- **refactor** - Code refactoring (no feature change, no bug fix)
|
||||
- **docs** - Documentation changes
|
||||
- **test** - Test changes
|
||||
- **chore** - Build, dependencies, tooling changes
|
||||
- **perf** - Performance improvements
|
||||
|
||||
### Key Rule: Always List Affected Packages
|
||||
|
||||
For every commit, **explicitly mention all packages/directories that were modified**. This is crucial for understanding the scope of changes.
|
||||
|
||||
```
|
||||
[fix]: Handle null pointer in model response
|
||||
|
||||
Affected packages:
|
||||
- core/providers/openai/
|
||||
- core/schemas/
|
||||
|
||||
Impact: Fixes intermittent crashes when provider returns malformed response
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
**Good:**
|
||||
```
|
||||
[feat]: Add retry logic to MCP client manager
|
||||
|
||||
Implements exponential backoff for transient errors (connection timeouts, network issues).
|
||||
Retries only for transient errors, fails immediately for permanent errors (auth, config).
|
||||
|
||||
Affected packages:
|
||||
- core/mcp/clientmanager.go - Connection retry logic
|
||||
- core/mcp/utils.go - Retry executor and error classification
|
||||
- core/mcp/healthmonitor.go - Automatic reconnection
|
||||
|
||||
Tests:
|
||||
- Added tests for retry backoff progression
|
||||
- Added tests for error classification
|
||||
```
|
||||
|
||||
**Better (if changes are significant to multiple packages):**
|
||||
```
|
||||
[feat]: Add resilient MCP connection handling
|
||||
|
||||
Commit 1: [feat]: MCP utils - Add retry executor with exponential backoff
|
||||
Commit 2: [fix]: MCP client - Use retry logic for connection establishment
|
||||
Commit 3: [feat]: MCP health monitor - Add automatic reconnection
|
||||
```
|
||||
|
||||
## Go Code Conventions
|
||||
|
||||
### Style Guidelines
|
||||
|
||||
1. **Follow standard Go conventions**
|
||||
- Use `gofmt` for formatting
|
||||
- Run `make fmt` before committing
|
||||
|
||||
2. **Naming**
|
||||
- Use meaningful variable names
|
||||
- Avoid single letters except in loops
|
||||
- Use `camelCase` for variables and functions
|
||||
- Use `PascalCase` for exported types
|
||||
|
||||
3. **Comments**
|
||||
- Comment exported functions and types
|
||||
- Use clear, concise comments
|
||||
- Explain *why*, not *what*
|
||||
|
||||
4. **Error Handling**
|
||||
- Always check and handle errors
|
||||
- Provide context in error messages
|
||||
- Don't ignore errors with `_`
|
||||
|
||||
### Structure
|
||||
|
||||
```go
|
||||
// Exported functions first
|
||||
func NewClient(config Config) (*Client, error) {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// Exported methods
|
||||
func (c *Client) Do(ctx context.Context) error {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// Unexported helper functions
|
||||
func (c *Client) validate() error {
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
Each package should have:
|
||||
- A `package` comment
|
||||
- Exported function/type comments
|
||||
- Complex logic explanations
|
||||
|
||||
```go
|
||||
// Package mcp provides Model Context Protocol integration
|
||||
// for connecting AI models to external tools and services.
|
||||
package mcp
|
||||
|
||||
// Client manages connections to MCP servers.
|
||||
type Client struct {
|
||||
// fields...
|
||||
}
|
||||
|
||||
// Connect establishes a connection to the MCP server.
|
||||
// Returns an error if the connection fails.
|
||||
func (c *Client) Connect(ctx context.Context) error {
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript/React Code Conventions
|
||||
|
||||
### Style Guidelines
|
||||
|
||||
1. **Use TypeScript** - Avoid `any` types when possible
|
||||
2. **Use functional components** - No class components
|
||||
3. **Props interface**
|
||||
```typescript
|
||||
interface ButtonProps {
|
||||
onClick: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
```
|
||||
|
||||
4. **Naming**
|
||||
- Components: `PascalCase`
|
||||
- Functions/variables: `camelCase`
|
||||
- Constants: `UPPER_SNAKE_CASE`
|
||||
|
||||
### Structure
|
||||
|
||||
```typescript
|
||||
// Imports
|
||||
import React from 'react';
|
||||
import { useContext } from 'react';
|
||||
|
||||
// Types
|
||||
interface Props {
|
||||
id: string;
|
||||
onSubmit: (data: FormData) => Promise<void>;
|
||||
}
|
||||
|
||||
// Component
|
||||
export const MyComponent: React.FC<Props> = ({ id, onSubmit }) => {
|
||||
return (
|
||||
<div>
|
||||
{/* implementation */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Testing Conventions
|
||||
|
||||
### Go Tests
|
||||
|
||||
1. **Test file naming**: `*_test.go`
|
||||
2. **Test function naming**: `Test<FunctionName>`
|
||||
3. **Table-driven tests for multiple cases**
|
||||
|
||||
```go
|
||||
func TestProcessRequest(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{"valid input", "test", "result", false},
|
||||
{"invalid input", "", "", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ProcessRequest(tt.input)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("got %s, want %s", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
make test-all
|
||||
|
||||
# Run specific test suite
|
||||
make test-core PROVIDER=openai
|
||||
|
||||
# Run specific test case
|
||||
make test-core PROVIDER=openai TESTCASE=TestName/SubTest
|
||||
```
|
||||
|
||||
## Documentation Conventions
|
||||
|
||||
### MDX Files
|
||||
|
||||
1. **Front matter**
|
||||
```mdx
|
||||
---
|
||||
title: "Feature Name"
|
||||
description: "Brief description of the feature"
|
||||
icon: "icon-name"
|
||||
---
|
||||
```
|
||||
|
||||
2. **Headings** - Use H2 (`##`) as top level in body
|
||||
3. **Code blocks** - Always include language: ` ```go`
|
||||
4. **Links** - Use relative paths: `/features/caching`
|
||||
|
||||
### Examples
|
||||
|
||||
```mdx
|
||||
---
|
||||
title: "Semantic Caching"
|
||||
description: "Intelligent response caching based on semantic similarity"
|
||||
icon: "database"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Semantic caching intelligently caches responses...
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
semantic_cache:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
<Note>
|
||||
This is important information that needs highlighting.
|
||||
</Note>
|
||||
|
||||
## Benefits
|
||||
|
||||
- Reduces costs by 30-40%
|
||||
- Improves latency for similar queries
|
||||
```
|
||||
|
||||
## Pull Request Conventions
|
||||
|
||||
See [Raising a PR](/contributing/raising-a-pr) for detailed guidelines. Key points:
|
||||
|
||||
1. **Commit messages**: Follow `[type]: description` format
|
||||
2. **Package listing**: Always mention affected packages
|
||||
3. **Changelog updates**: Update `changelog.md` for each affected package
|
||||
4. **Tests**: Ensure all tests pass before opening PR
|
||||
5. **Documentation**: Update docs if behavior changes
|
||||
|
||||
## Changelog Format
|
||||
|
||||
For each package you modify, update its `changelog.md` file at the top with:
|
||||
|
||||
```
|
||||
[type]: description [@Your Name](https://github.com/yourname)
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
[feat]: add semantic caching support for image generation [@prathammaxim](https://github.com/prathammaxim)
|
||||
[fix]: handle null pointer in response parsing [@username](https://github.com/username)
|
||||
[refactor]: simplify model caching logic [@username](https://github.com/username)
|
||||
```
|
||||
|
||||
**File locations:**
|
||||
- `core/changelog.md`
|
||||
- `framework/changelog.md`
|
||||
- `transports/changelog.md`
|
||||
- `plugins/{plugin-name}/changelog.md`
|
||||
|
||||
## Code Quality Standards
|
||||
|
||||
Before submitting code:
|
||||
|
||||
### Go Code
|
||||
```bash
|
||||
# Format code
|
||||
make fmt
|
||||
|
||||
# Run linter
|
||||
make lint
|
||||
|
||||
# Run tests
|
||||
make test-all
|
||||
```
|
||||
|
||||
### TypeScript/React
|
||||
- Use ESLint configuration from project
|
||||
- Run `npm run format` for formatting
|
||||
- Ensure TypeScript compilation succeeds
|
||||
|
||||
## Key Principles
|
||||
|
||||
1. **Clarity** - Code should be easy to understand
|
||||
2. **Consistency** - Follow existing patterns in codebase
|
||||
3. **Testing** - All code should have tests
|
||||
4. **Documentation** - Document public APIs and complex logic
|
||||
5. **Simplicity** - Avoid over-engineering
|
||||
6. **Performance** - Consider performance implications of changes
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
❌ **Don't:**
|
||||
- Submit PRs without running tests
|
||||
- Use `fmt.Println` for logging (use logger)
|
||||
- Ignore error handling
|
||||
- Create huge functions (>100 lines)
|
||||
- Mix refactoring with feature changes
|
||||
- Forget to list affected packages in commit messages
|
||||
|
||||
✅ **Do:**
|
||||
- Run `make test-all` before opening PR
|
||||
- Use structured logging
|
||||
- Handle all error cases
|
||||
- Keep functions focused and testable
|
||||
- Make logical, focused commits
|
||||
- Always mention affected packages and changes
|
||||
|
||||
## Getting Help
|
||||
|
||||
- See [Setting up the repository](/contributing/setting-up-repo) for development setup
|
||||
- Check [Architecture docs](/architecture) to understand the codebase
|
||||
- Ask in [Discord](https://discord.gg/exN5KAydbU) if you have questions
|
||||
506
docs/contributing/raising-a-pr.mdx
Normal file
506
docs/contributing/raising-a-pr.mdx
Normal file
@@ -0,0 +1,506 @@
|
||||
---
|
||||
title: "Raising a Pull Request"
|
||||
description: "Guidelines for submitting high-quality pull requests to Bifrost."
|
||||
icon: "code-pull-request"
|
||||
---
|
||||
|
||||
## Before You Start
|
||||
|
||||
1. **Create an issue first** (if one doesn't exist) - Discuss the change with the maintainers
|
||||
2. **Fork the repository** and create a feature branch
|
||||
3. **Set up your development environment** using [these instructions](/contributing/setting-up-repo)
|
||||
4. **Run tests locally** to ensure everything works
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
All commits should follow a standardized format. **For each package/directory you modify, include a separate commit message line** describing the change in that package.
|
||||
|
||||
### Format
|
||||
|
||||
```
|
||||
[type]: description
|
||||
|
||||
Additional details if needed (optional)
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
- **feat** - New feature
|
||||
- **fix** - Bug fix
|
||||
- **refactor** - Code refactoring (no feature change, no bug fix)
|
||||
- **docs** - Documentation changes
|
||||
- **test** - Test changes
|
||||
- **chore** - Build, dependencies, tooling changes
|
||||
- **perf** - Performance improvements
|
||||
|
||||
### Examples
|
||||
|
||||
**Single Package Change:**
|
||||
```
|
||||
[fix]: handle connection timeout in MCP client manager
|
||||
```
|
||||
|
||||
**Multiple Packages:**
|
||||
If your change affects multiple packages, include the package name or affected module in the description:
|
||||
|
||||
```
|
||||
[fix]: MCP client - add retry logic to connection establishment
|
||||
|
||||
This fixes intermittent connection failures by implementing exponential backoff.
|
||||
Affected packages:
|
||||
- core/mcp/clientmanager.go
|
||||
- core/mcp/healthmonitor.go
|
||||
```
|
||||
|
||||
**Provider-Specific Changes:**
|
||||
```
|
||||
[fix]: OpenAI provider - handle streaming response errors
|
||||
[feat]: Anthropic provider - add support for batch API
|
||||
```
|
||||
|
||||
**Multiple Commits for Multiple Packages:**
|
||||
If you're making significant changes to multiple packages, consider separate commits:
|
||||
|
||||
```bash
|
||||
git commit -m "[feat]: Add retry mechanism to MCP core utilities"
|
||||
git commit -m "[fix]: Update OpenAI integration with retry support"
|
||||
git commit -m "[docs]: Document MCP resilience strategy"
|
||||
```
|
||||
|
||||
### All Packages Modified Should Be Listed
|
||||
|
||||
When creating a commit, always mention which packages/components are affected:
|
||||
|
||||
```
|
||||
[feat]: Add semantic caching plugin
|
||||
|
||||
Changes:
|
||||
- plugins/semanticcache/ - Core caching logic
|
||||
- core/bifrost.go - Plugin registration
|
||||
- transports/bifrost-http/server.go - Cache middleware integration
|
||||
|
||||
Benefits:
|
||||
- Reduces API costs by 30-40%
|
||||
- Improves response latency for similar queries
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Use a structured format that makes it easy to understand at a glance what changed and where.
|
||||
</Tip>
|
||||
|
||||
## Maintaining Changelogs
|
||||
|
||||
For each package you modify, update the corresponding `changelog.md` file with your changes. Changelog entries are used to generate release notes and communicate changes to users.
|
||||
|
||||
### Changelog File Locations
|
||||
|
||||
Each package that receives updates should have a `changelog.md` file:
|
||||
|
||||
- `core/changelog.md` - Core package changes
|
||||
- `framework/changelog.md` - Framework changes
|
||||
- `transports/changelog.md` - Transport layer changes
|
||||
- `plugins/{plugin-name}/changelog.md` - Specific plugin changes
|
||||
|
||||
### Changelog Entry Format
|
||||
|
||||
Each changelog entry follows this exact format:
|
||||
|
||||
```
|
||||
[type]: description [@Your Name](https://github.com/yourname)
|
||||
```
|
||||
|
||||
**Required Components:**
|
||||
- **Type**: One of `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, or `perf`
|
||||
- **Description**: Clear, concise description (under 100 characters)
|
||||
- **Author**: Your GitHub profile link (recommended)
|
||||
|
||||
### Change Types Reference
|
||||
|
||||
| Type | Usage | Example |
|
||||
|------|-------|---------|
|
||||
| **feat** | New feature | `[feat]: add exponential backoff retry mechanism` |
|
||||
| **fix** | Bug fix | `[fix]: handle connection timeout in MCP client` |
|
||||
| **refactor** | Code refactoring (no behavior change) | `[refactor]: simplify model caching` |
|
||||
| **docs** | Documentation updates | `[docs]: clarify semantic caching behavior` |
|
||||
| **test** | Test additions/modifications | `[test]: add regression tests for retry logic` |
|
||||
| **chore** | Build, dependencies, tooling | `[chore]: upgrade dependencies to latest versions` |
|
||||
| **perf** | Performance improvements | `[perf]: optimize model lookup to O(1)` |
|
||||
|
||||
### Changelog Examples
|
||||
|
||||
**Good Examples:**
|
||||
```markdown
|
||||
[feat]: add exponential backoff retry mechanism [@prathammaxim](https://github.com/prathammaxim)
|
||||
[fix]: handle null pointer in OpenAI response parsing [@contributor](https://github.com/contributor)
|
||||
[perf]: optimize model lookup with hash map [@contributor](https://github.com/contributor)
|
||||
```
|
||||
|
||||
**Poor Examples (avoid):**
|
||||
```markdown
|
||||
- update stuff
|
||||
- minor changes
|
||||
- fix bug
|
||||
- added new thing
|
||||
```
|
||||
|
||||
### How to Add Changelog Entries
|
||||
|
||||
1. **Edit the `changelog.md`** file in the affected package
|
||||
2. **Add new entry at the TOP** of the file (most recent first)
|
||||
3. **Follow the exact format**: `[type]: description [@name](https://github.com/user)`
|
||||
4. **Include your author link** (optional but recommended)
|
||||
|
||||
**Example: Before and After**
|
||||
|
||||
**Before:**
|
||||
```markdown
|
||||
[feat]: added image generation request and response support
|
||||
[chore]: added case-insensitive helper methods
|
||||
```
|
||||
|
||||
**After (with new entry at top):**
|
||||
```markdown
|
||||
[fix]: handle connection timeout in retry logic [@your-name](https://github.com/your-name)
|
||||
[feat]: add exponential backoff for transient errors [@your-name](https://github.com/your-name)
|
||||
[feat]: added image generation request and response support
|
||||
[chore]: added case-insensitive helper methods
|
||||
```
|
||||
|
||||
### Multiple Package Changes
|
||||
|
||||
When your PR affects multiple packages, **add entries to each package's `changelog.md`**:
|
||||
|
||||
**Example Multi-Package Changelog:**
|
||||
|
||||
**core/changelog.md:**
|
||||
```markdown
|
||||
[feat]: add retry executor with exponential backoff [@contributor](https://github.com/contributor)
|
||||
```
|
||||
|
||||
**transports/changelog.md:**
|
||||
```markdown
|
||||
[fix]: apply retry logic to connection establishment [@contributor](https://github.com/contributor)
|
||||
```
|
||||
|
||||
**plugins/governance/changelog.md:**
|
||||
```markdown
|
||||
[chore]: update core dependency to latest version
|
||||
```
|
||||
|
||||
### What to Include in Changelog
|
||||
|
||||
✅ **Do include:**
|
||||
- Bug fixes that affect users
|
||||
- New features
|
||||
- Breaking changes
|
||||
- Performance improvements
|
||||
- Significant refactoring
|
||||
- Documentation improvements
|
||||
|
||||
❌ **Don't include:**
|
||||
- Internal code cleanup with no user impact
|
||||
- Typo fixes in comments only
|
||||
- Build system changes (unless significant)
|
||||
- Minor test-only changes
|
||||
|
||||
### Changelog Best Practices
|
||||
|
||||
1. **Add entries at the TOP** of the `changelog.md` file (most recent first)
|
||||
2. **One entry per logical change** - Don't combine unrelated changes
|
||||
3. **Keep descriptions concise** - Under 100 characters
|
||||
4. **Use consistent format** - `[type]: description`
|
||||
5. **Include your GitHub link** - Helps recognize contributors
|
||||
6. **Update all affected package changelogs** - Don't forget secondary packages
|
||||
7. **Add changelog entry with your commit** - Don't wait until the end
|
||||
|
||||
### Format Consistency Rules
|
||||
|
||||
**DO's:**
|
||||
- ✅ Use square brackets: `[feat]`
|
||||
- ✅ Use colon separator: `[feat]:`
|
||||
- ✅ Start with lowercase (unless proper noun)
|
||||
- ✅ Be specific and concise
|
||||
- ✅ Include GitHub profile link
|
||||
- ✅ Add new entries at the top
|
||||
|
||||
**DON'Ts:**
|
||||
- ❌ Don't use parentheses: `(feat)` or braces `{feat}`
|
||||
- ❌ Don't use multiple spaces
|
||||
- ❌ Don't mix formats in the same file
|
||||
- ❌ Don't add entries at the bottom
|
||||
- ❌ Don't use vague descriptions
|
||||
|
||||
### Complete PR Example with Changelogs
|
||||
|
||||
If your PR adds retry logic to multiple packages:
|
||||
|
||||
```
|
||||
Commit: [feat]: Add retry logic with exponential backoff
|
||||
|
||||
Modified files:
|
||||
- core/mcp/utils.go ← add retry executor
|
||||
- core/mcp/clientmanager.go ← use retry logic
|
||||
|
||||
Update changelogs:
|
||||
|
||||
1. core/changelog.md:
|
||||
[feat]: add exponential backoff retry mechanism [@your-name](https://github.com/your-name)
|
||||
|
||||
2. transports/changelog.md:
|
||||
[fix]: apply retry logic to connection establishment [@your-name](https://github.com/your-name)
|
||||
```
|
||||
|
||||
### Changelog Review Checklist
|
||||
|
||||
Before submitting a PR, verify:
|
||||
|
||||
- [ ] All packages modified have changelog entries
|
||||
- [ ] Format is correct: `[type]: description [@name](https://github.com/user)`
|
||||
- [ ] Entries are added at TOP of the file
|
||||
- [ ] Author GitHub link is included
|
||||
- [ ] Description is clear and concise (under 100 chars)
|
||||
- [ ] Type is one of: feat, fix, refactor, docs, test, chore, perf
|
||||
- [ ] Entries are added with the commit (not after)
|
||||
|
||||
## Pull Request Title
|
||||
|
||||
Keep PR titles concise and descriptive, following the same pattern:
|
||||
|
||||
```
|
||||
[type]: Brief description of the change
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `[feat]: Add rate limiting to governance plugin`
|
||||
- `[fix]: Resolve deadlock in MCP retry logic`
|
||||
- `[refactor]: Simplify model caching mechanism`
|
||||
- `[docs]: Update contribution guidelines for commit messages`
|
||||
|
||||
## Pull Request Description
|
||||
|
||||
Use the following template for your PR description:
|
||||
|
||||
```markdown
|
||||
## Description
|
||||
|
||||
Brief explanation of what this PR does and why it's needed.
|
||||
|
||||
## Type of Change
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature
|
||||
- [ ] Breaking change
|
||||
- [ ] Documentation update
|
||||
- [ ] Refactoring
|
||||
|
||||
## Affected Packages
|
||||
|
||||
List all packages/directories modified:
|
||||
- core/providers/openai/
|
||||
- transports/bifrost-http/server/
|
||||
- plugins/governance/
|
||||
|
||||
## Changes Made
|
||||
|
||||
- Specific change 1
|
||||
- Specific change 2
|
||||
- Specific change 3
|
||||
|
||||
## Testing
|
||||
|
||||
Describe how you tested these changes:
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Integration tests passed
|
||||
- [ ] Manual testing completed
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Code follows the project's code style
|
||||
- [ ] Tests are passing locally (`make test-all`)
|
||||
- [ ] Documentation is updated if needed
|
||||
- [ ] No breaking changes (or breaking changes are documented)
|
||||
- [ ] Commit messages follow the format: `[type]: description`
|
||||
- [ ] All affected packages are mentioned in commit messages
|
||||
|
||||
## Related Issues
|
||||
|
||||
Closes #123
|
||||
Relates to #456
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Keep PRs Focused
|
||||
|
||||
- One feature or fix per PR when possible
|
||||
- If multiple related changes, group them logically by package
|
||||
- Avoid mixing refactoring with feature changes
|
||||
|
||||
### 2. Commit Messages Matter
|
||||
|
||||
❌ **Bad:**
|
||||
```
|
||||
Update file
|
||||
```
|
||||
|
||||
✅ **Good:**
|
||||
```
|
||||
[fix]: Handle null pointer in OpenAI response parsing
|
||||
```
|
||||
|
||||
❌ **Bad:**
|
||||
```
|
||||
[feat]: Major update to semantic cache
|
||||
```
|
||||
|
||||
✅ **Good:**
|
||||
```
|
||||
[feat]: Add semantic cache initialization with retry logic
|
||||
|
||||
Changes:
|
||||
- plugins/semanticcache/ - Add retry mechanism
|
||||
- core/bifrost.go - Register cache handler
|
||||
- docs/ - Add usage documentation
|
||||
```
|
||||
|
||||
### 3. Include All Affected Packages
|
||||
|
||||
Always explicitly list which packages/directories are modified:
|
||||
|
||||
```
|
||||
[fix]: Resolve SSE connection issues
|
||||
|
||||
Affected components:
|
||||
- core/mcp/clientmanager.go - Add connection validation
|
||||
- core/mcp/healthmonitor.go - Improve health checks
|
||||
- core/mcp/utils.go - Fix retry context handling
|
||||
```
|
||||
|
||||
### 4. Test Thoroughly
|
||||
|
||||
Before opening a PR:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
make test-all
|
||||
|
||||
# Run specific test suite
|
||||
make test-core PROVIDER=openai
|
||||
|
||||
# Format code
|
||||
make fmt
|
||||
|
||||
# Lint code
|
||||
make lint
|
||||
```
|
||||
|
||||
### 5. Small, Reviewable PRs
|
||||
|
||||
- Aim for <400 lines changed per PR
|
||||
- If larger, break into logical commits
|
||||
- Each commit should be independently reviewable
|
||||
|
||||
### 6. Update Documentation
|
||||
|
||||
- Update relevant `.mdx` files in `/docs`
|
||||
- Add comments for complex logic
|
||||
- Update README.md if behavior changes
|
||||
|
||||
## Code Review Checklist
|
||||
|
||||
Before requesting review, ensure:
|
||||
|
||||
✅ All commits follow `[type]: description` format
|
||||
✅ All affected packages are explicitly mentioned
|
||||
✅ No merge conflicts
|
||||
✅ All tests pass (`make test-all`)
|
||||
✅ Code is properly formatted (`make fmt`)
|
||||
✅ No linting issues (`make lint`)
|
||||
✅ Documentation is updated
|
||||
✅ PR description is clear and complete
|
||||
|
||||
## During Code Review
|
||||
|
||||
- Respond to feedback promptly
|
||||
- Push new commits for requested changes (don't force-push to avoid confusion)
|
||||
- Mark conversations as resolved when addressed
|
||||
- Ask for clarification if feedback is unclear
|
||||
|
||||
## Merging
|
||||
|
||||
Once approved:
|
||||
- The maintainer will handle the merge
|
||||
- Your commits will be preserved in the history
|
||||
- Ensure your branch is up-to-date with `main` before final approval
|
||||
|
||||
## Common Pitfalls to Avoid
|
||||
|
||||
1. ❌ **Vague commit messages** - Always be specific about what changed
|
||||
2. ❌ **Missing package information** - Always list affected packages
|
||||
3. ❌ **Mixing concerns** - Keep commits focused
|
||||
4. ❌ **Not running tests** - Test locally before opening PR
|
||||
5. ❌ **Large PRs** - Break into smaller, reviewable chunks
|
||||
6. ❌ **Not updating docs** - If behavior changes, update documentation
|
||||
|
||||
## Examples of Good Commits
|
||||
|
||||
### Example 1: Provider Fix
|
||||
```
|
||||
[fix]: OpenAI provider - handle streaming response errors correctly
|
||||
|
||||
Previously, streaming responses would sometimes fail with
|
||||
"context deadline exceeded" error when network latency exceeded
|
||||
timeout threshold.
|
||||
|
||||
Changes:
|
||||
- core/providers/openai/openai.go - Add dynamic timeout
|
||||
- core/providers/anthropic/anthropic.go - Align timeout logic
|
||||
- tests/ - Add regression tests
|
||||
|
||||
Affected packages:
|
||||
- core/providers/
|
||||
- core/bifrost.go (minor type update)
|
||||
```
|
||||
|
||||
### Example 2: Plugin Development
|
||||
```
|
||||
[feat]: Add rate limiting to governance plugin
|
||||
|
||||
Introduces token bucket algorithm for per-customer rate limiting.
|
||||
Allows fine-grained control over request throughput.
|
||||
|
||||
Changes:
|
||||
- plugins/governance/ratelimit/ - New package with core logic
|
||||
- plugins/governance/main.go - Register rate limiter
|
||||
- transports/bifrost-http/middleware.go - Apply rate limit checks
|
||||
- docs/features/governance.mdx - Add usage documentation
|
||||
|
||||
Benefits:
|
||||
- Prevents request storms
|
||||
- Fair resource allocation
|
||||
- Configurable per-customer
|
||||
```
|
||||
|
||||
### Example 3: Core Refactoring
|
||||
```
|
||||
[refactor]: Simplify model caching to reduce complexity
|
||||
|
||||
Consolidate three separate caching layers into unified approach.
|
||||
No behavior change - internal improvement only.
|
||||
|
||||
Changes:
|
||||
- core/models.go - Unified cache implementation
|
||||
- core/cache/ - Remove legacy cache package
|
||||
- tests/ - Update cache tests
|
||||
|
||||
Affected packages:
|
||||
- core/ (main change)
|
||||
- plugins/ (minor - cache API unchanged)
|
||||
```
|
||||
|
||||
## Need Help?
|
||||
|
||||
- 📚 See [Code Conventions](/contributing/code-conventions) for style guidelines
|
||||
- 🏗️ Check [Architecture Docs](/architecture) to understand the codebase structure
|
||||
- 💬 Ask in [Discord](https://discord.gg/exN5KAydbU) if unsure about the process
|
||||
- ❓ Refer to the [Changelog Review Checklist](#changelog-review-checklist) above before submitting
|
||||
0
docs/contributing/running-tests.mdx
Normal file
0
docs/contributing/running-tests.mdx
Normal file
420
docs/contributing/setting-up-repo.mdx
Normal file
420
docs/contributing/setting-up-repo.mdx
Normal file
@@ -0,0 +1,420 @@
|
||||
---
|
||||
title: "Setting up the repository"
|
||||
description: "Complete guide to setting up the Bifrost repository for local development."
|
||||
icon: "hammer"
|
||||
---
|
||||
|
||||
This guide walks you through setting up the Bifrost repository for local development, from prerequisites to running your first development server.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before setting up the repository, ensure you have the following tools installed:
|
||||
- [Go](https://go.dev/doc/install) (1.25.5)
|
||||
- [Node.js](https://nodejs.org/en/download) (>= 18.0.0) and npm
|
||||
- [Make](/deployment-guides/how-to/install-make)
|
||||
- [Docker](https://www.docker.com) (optional, for containerized development)
|
||||
- [Air](https://github.com/air-verse/air?tab=readme-ov-file#installation) (for hot reloading, auto-installed by Makefile when needed)
|
||||
- [golangci-lint](https://golangci-lint.run/usage/install/) (optional, for linting)
|
||||
- [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) (optional, for code formatting)
|
||||
|
||||
<Note>`gotestsum` and `junit-viewer` are auto-installed by make commands when needed for test reporting.</Note>
|
||||
|
||||
## Clone the Repository
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/maximhq/bifrost.git
|
||||
cd bifrost
|
||||
|
||||
# Verify the repository structure
|
||||
ls -la
|
||||
```
|
||||
|
||||
You should see the main directories: `core/`, `framework/`, `transports/`, `ui/`, `plugins/`, `docs/`, etc.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
Bifrost uses a modular architecture with the following structure:
|
||||
|
||||
```
|
||||
bifrost/
|
||||
├── core/ # Core functionality and shared components
|
||||
│ ├── providers/ # Provider-specific implementations (OpenAI, Anthropic, etc.)
|
||||
│ ├── schemas/ # Interfaces and structs used throughout Bifrost
|
||||
│ └── bifrost.go # Main Bifrost implementation
|
||||
├── framework/ # Framework components for common functionality
|
||||
│ ├── configstore/ # Configuration storages
|
||||
│ ├── logstore/ # Request logging storages
|
||||
│ └── vectorstore/ # Vector storages
|
||||
├── transports/ # HTTP gateway and other interface layers
|
||||
│ └── bifrost-http/ # HTTP transport implementation
|
||||
├── ui/ # Web interface for HTTP gateway
|
||||
├── plugins/ # First party plugins
|
||||
├── docs/ # Documentation and guides
|
||||
└── tests/ # Comprehensive test suites
|
||||
```
|
||||
|
||||
The system uses a provider-agnostic approach with well-defined interfaces in `core/schemas/` for easy extension to new AI providers.
|
||||
|
||||
**Learn More About the Architecture:**
|
||||
- **[Request Flow](/architecture/core/request-flow)** - Deep dive into how requests are processed from transport to provider
|
||||
- **[Plugin System](/architecture/core/plugins)** - How plugins extend functionality
|
||||
- **[Framework Components](/architecture/framework/what-is-framework)** - Shared storage and utilities
|
||||
- **[MCP Integration](/architecture/core/mcp)** - Model Context Protocol implementation
|
||||
|
||||
## Development Environment Setup
|
||||
|
||||
### Quick Start (Recommended)
|
||||
|
||||
<Note>
|
||||
If you're setting up the repo for the first time, you may need to build the project at least once:
|
||||
```bash
|
||||
make build LOCAL=1
|
||||
```
|
||||
</Note>
|
||||
|
||||
The fastest way to get started is using the complete development environment:
|
||||
|
||||
```bash
|
||||
# Start complete development environment (UI + API with hot reload)
|
||||
make dev
|
||||
```
|
||||
|
||||
This command will:
|
||||
1. Install UI dependencies automatically
|
||||
2. Install Air for hot reloading
|
||||
3. Set up the Go workspace with local modules
|
||||
4. Start the Vite development server (port 3000)
|
||||
5. Start the API server with UI proxy (port 8080)
|
||||
|
||||
**Access the application at:** http://localhost:8080
|
||||
|
||||
<Note>The `make dev` command handles all setup automatically. You can skip the manual setup steps below if this works for you.</Note>
|
||||
|
||||
#### Alternative: Using Pulse
|
||||
|
||||
If you prefer [Pulse](https://github.com/Pratham-Mishra04/pulse) over Air for hot reloading, use:
|
||||
|
||||
```bash
|
||||
make dev-pulse
|
||||
```
|
||||
|
||||
This runs the same development environment but uses `pulse.yaml` for hot reloading instead of `.air.toml`.
|
||||
|
||||
### Manual Setup (Alternative)
|
||||
|
||||
If you prefer to set up components manually:
|
||||
|
||||
#### 1. Install UI Dependencies
|
||||
|
||||
```bash
|
||||
# Install UI dependencies and tools
|
||||
make install-ui
|
||||
```
|
||||
|
||||
#### 2. Install Air for Hot Reloading
|
||||
|
||||
```bash
|
||||
# Install Air if not already installed
|
||||
make install-air
|
||||
```
|
||||
|
||||
#### 3. Set Up Go Workspace
|
||||
|
||||
```bash
|
||||
# Set up Go workspace with all local modules
|
||||
make setup-workspace
|
||||
```
|
||||
|
||||
This creates a `go.work` file that links all local modules for development.
|
||||
|
||||
#### 4. Build the Application
|
||||
|
||||
```bash
|
||||
# Build UI and binary
|
||||
make build
|
||||
|
||||
# Build with local go.work modules (for development)
|
||||
make build LOCAL=1
|
||||
|
||||
# Build with specific version
|
||||
make build VERSION=1.0.0
|
||||
|
||||
# Cross-compile for different platforms
|
||||
make build GOOS=linux GOARCH=amd64
|
||||
|
||||
# Build with dynamic linking (Linux only)
|
||||
make build DYNAMIC=1
|
||||
```
|
||||
|
||||
#### 5. Run the Application
|
||||
|
||||
```bash
|
||||
# Run without hot reload
|
||||
make run
|
||||
|
||||
# Or with hot reload (development)
|
||||
make dev
|
||||
```
|
||||
|
||||
## Available Make Commands
|
||||
|
||||
The Makefile provides numerous commands for development:
|
||||
|
||||
### Development Commands
|
||||
|
||||
```bash
|
||||
make dev # Start complete development environment using Air for hot reloading
|
||||
make dev-pulse # Start complete development environment using Pulse for hot reloading
|
||||
make build # Build UI and bifrost-http binary
|
||||
make run # Build and run (no hot reload)
|
||||
make clean # Clean build artifacts
|
||||
```
|
||||
|
||||
### Testing Commands
|
||||
|
||||
```bash
|
||||
make test # Run bifrost-http tests
|
||||
make test-core # Run all core tests
|
||||
make test-core PROVIDER=openai # Run specific provider tests
|
||||
make test-core PROVIDER=openai TESTCASE=SpeechSynthesisStreamAdvanced/MultipleVoices_Streaming/StreamingVoice_echo # Run specific test case
|
||||
make test-plugins # Run plugin tests
|
||||
make test-governance # Run governance tests
|
||||
make test-governance TESTCASE=TestVKBudgetExceeded # Run specific governance test
|
||||
make test-governance PATTERN=Budget # Run governance tests matching pattern
|
||||
make test-all # Run all tests
|
||||
make clean-test-reports # Clean test reports
|
||||
make generate-html-reports # Convert XML to HTML reports
|
||||
```
|
||||
|
||||
<Note>
|
||||
- **TESTCASE must use forward-slash separated nested path format** (e.g., `ParentTest/SubTest/SpecificTest`)
|
||||
- See the Makefile comment at line 311 for the expected format and additional examples
|
||||
- HTML test reports are automatically generated when `junit-viewer` is available
|
||||
- Reports are saved to `test-reports/` directory
|
||||
- View with: `open test-reports/index.html`
|
||||
</Note>
|
||||
|
||||
### Workspace Management
|
||||
|
||||
```bash
|
||||
make setup-workspace # Set up Go workspace for local development
|
||||
make work-clean # Remove local go.work files
|
||||
```
|
||||
|
||||
<Note>`make work-init` is deprecated. Use `make setup-workspace` instead.</Note>
|
||||
|
||||
### UI Commands
|
||||
|
||||
```bash
|
||||
make install-ui # Install UI dependencies
|
||||
make build-ui # Build UI for production
|
||||
```
|
||||
|
||||
### Docker Commands
|
||||
|
||||
```bash
|
||||
make build-docker-image # Build Docker image
|
||||
make docker-run # Run Docker container
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
```bash
|
||||
make docs # Start local documentation server
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
|
||||
```bash
|
||||
make lint # Run linter for Go code
|
||||
make fmt # Format Go code
|
||||
```
|
||||
|
||||
### Tool Installation
|
||||
|
||||
```bash
|
||||
make install-gotestsum # Install gotestsum for test reporting
|
||||
make install-junit-viewer # Install junit-viewer for HTML reports
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
You can customize the development environment with these variables:
|
||||
|
||||
```bash
|
||||
# Server configuration
|
||||
HOST=localhost # Server host (default: localhost)
|
||||
PORT=8080 # Server port (default: 8080)
|
||||
|
||||
# Logging
|
||||
LOG_STYLE=json # Logger format: json|pretty (default: json)
|
||||
LOG_LEVEL=info # Logger level: debug|info|warn|error (default: info)
|
||||
|
||||
# Prometheus
|
||||
PROMETHEUS_LABELS="env=dev" # Labels for Prometheus metrics
|
||||
|
||||
# App directory
|
||||
APP_DIR= # App data directory (empty by default, /app/data recommended for containers)
|
||||
|
||||
# Build configuration
|
||||
VERSION=dev-build # Build version (default: dev-build)
|
||||
LOCAL= # Use local go.work for builds (e.g., make build LOCAL=1)
|
||||
```
|
||||
|
||||
Example with custom settings:
|
||||
|
||||
```bash
|
||||
PORT=3001 LOG_STYLE=pretty LOG_LEVEL=debug APP_DIR=/app/data make dev
|
||||
```
|
||||
|
||||
## Understanding Bifrost Architecture
|
||||
|
||||
Before diving into development, it's helpful to understand how Bifrost works internally. The architecture documentation provides detailed insights into:
|
||||
|
||||
### Core Components
|
||||
- **[Request Flow](/architecture/core/request-flow)** - How requests flow through the system from transport to provider and back
|
||||
- **[Concurrency](/architecture/core/concurrency)** - Worker pools and threading model
|
||||
- **[MCP Integration](/architecture/core/mcp)** - Model Context Protocol implementation
|
||||
- **[Plugin System](/architecture/core/plugins)** - How plugins extend core functionality
|
||||
|
||||
### Framework Layer
|
||||
- **[What is Framework](/architecture/framework/what-is-framework)** - Shared storage and utilities overview
|
||||
- **[Config Store](/architecture/framework/config-store)** - Configuration persistence patterns
|
||||
- **[Log Store](/architecture/framework/log-store)** - Request logging and analytics
|
||||
- **[Vector Store](/architecture/framework/vector-store)** - Semantic search and caching
|
||||
|
||||
### Plugins & Transports
|
||||
- **[Plugin Architecture](/architecture/core/plugins)** - Plugin development patterns and execution model
|
||||
- **[Transport Layer](/architecture/transports/in-memory-store)** - HTTP and other transport implementations
|
||||
|
||||
<Note>Reading the architecture documentation will help you understand where to make changes and how different components interact.</Note>
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### 1. Start Development Environment
|
||||
|
||||
```bash
|
||||
make dev
|
||||
```
|
||||
|
||||
### 2. Make Your Changes
|
||||
|
||||
- **Core changes**: Edit files in `core/`
|
||||
- **API changes**: Edit files in `transports/bifrost-http/`
|
||||
- **UI changes**: Edit files in `ui/`
|
||||
- **Plugin changes**: Edit files in `plugins/`
|
||||
|
||||
### 3. Test Your Changes
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
make test-all
|
||||
|
||||
# Run specific provider tests
|
||||
make test-core PROVIDER=openai
|
||||
|
||||
# Run specific test case (TESTCASE must be a slash-delimited nested path matching the test hierarchy)
|
||||
make test-core PROVIDER=elevenlabs TESTCASE=SpeechSynthesisStreamAdvanced/MultipleVoices_Streaming/StreamingVoice_echo
|
||||
|
||||
# Run HTTP transport tests
|
||||
make test
|
||||
|
||||
# Run plugin tests
|
||||
make test-plugins
|
||||
|
||||
# View test reports (after running tests)
|
||||
open test-reports/index.html
|
||||
```
|
||||
|
||||
### 4. Verify Code Quality
|
||||
|
||||
```bash
|
||||
# Format code
|
||||
make fmt
|
||||
|
||||
# Run linter
|
||||
make lint
|
||||
```
|
||||
|
||||
### 5. Build for Production
|
||||
|
||||
```bash
|
||||
# Build everything
|
||||
make build
|
||||
|
||||
# Or build Docker image
|
||||
make build-docker-image
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Go workspace issues:**
|
||||
```bash
|
||||
# Reset the workspace
|
||||
make work-clean
|
||||
make setup-workspace
|
||||
```
|
||||
|
||||
**UI dependency issues:**
|
||||
```bash
|
||||
# Clean and reinstall UI dependencies
|
||||
rm -rf ui/node_modules
|
||||
make install-ui
|
||||
```
|
||||
|
||||
**Port conflicts:**
|
||||
```bash
|
||||
# Use different ports
|
||||
PORT=9090 make dev
|
||||
```
|
||||
|
||||
If an process is running on a port you need to use, you may need to terminate or kill it first:
|
||||
```bash
|
||||
# Kill the process on port 8080
|
||||
kill -9 $(lsof -t -i:8080)
|
||||
```
|
||||
|
||||
**Hot reload not working:**
|
||||
```bash
|
||||
# Ensure Air is installed
|
||||
which air || go install github.com/air-verse/air@latest
|
||||
|
||||
# Check if .air.toml exists in transports/bifrost-http/
|
||||
ls transports/bifrost-http/.air.toml
|
||||
|
||||
# Alternatively, use Pulse instead of Air
|
||||
make dev-pulse
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
- **Check logs**: Development logs appear in your terminal
|
||||
- **Verify prerequisites**: Ensure Go, Node.js, and make are properly installed
|
||||
- **Clean build**: Run `make clean` and try again
|
||||
- **Discord**: Join our [Discord community](https://discord.gg/exN5KAydbU) for real-time help
|
||||
|
||||
## Next Steps
|
||||
|
||||
Once your development environment is running:
|
||||
|
||||
1. **Explore the UI**: Visit http://localhost:8080 to see the web interface
|
||||
2. **Make API calls**: Test the API endpoints at http://localhost:8080/v1/
|
||||
3. **Understand the architecture**: Read our [request flow documentation](/architecture/core/request-flow) to understand how Bifrost works internally
|
||||
4. **Read the documentation**: Check out our [complete documentation](https://docs.getbifrost.ai)
|
||||
5. **Review contribution guidelines**: See our [code conventions](/contributing/code-conventions) and [PR guidelines](/contributing/raising-a-pr)
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Essential commands for daily development
|
||||
make dev # Start development environment
|
||||
make test-all # Run all tests
|
||||
make fmt # Format code
|
||||
make clean # Clean build artifacts
|
||||
make help # Show all available commands
|
||||
```
|
||||
|
||||
Happy coding! 🚀
|
||||
Reference in New Issue
Block a user