Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ body:
attributes:
value: |
Thanks for proposing a feature. flux is the LLM client + skill router
that backs the hawk-eco ecosystem. Every feature is evaluated against
that backs the rho-eco ecosystem. Every feature is evaluated against
whether it serves **a single developer** running an AI agent locally.

Before submitting:
Expand Down Expand Up @@ -65,6 +65,6 @@ body:
description: flux avoids enterprise scope. Confirm this feature respects that.
options:
- label: Works with zero configuration (sensible defaults).
- label: Does not require a network call to a hawk-eco service.
- label: Does not require a network call to a rho-eco service.
- label: Stores any state locally by default.
- label: Has an escape hatch (override via flag, env, or config).
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Strict CI pipeline for hawk-eco Go repos.
# Strict CI pipeline for rho-eco Go repos.
# All jobs must pass — no continue-on-error except where explicitly noted.

name: CI
Expand Down
14 changes: 7 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ When starting any new work (feature, fix, refactor, chore), always create a feat

## Observability

See [hawk/docs/OTEL-CONVENTIONS.md](https://github.com/GrayCodeAI/hawk/blob/main/docs/OTEL-CONVENTIONS.md) for the shared OpenTelemetry attribute vocabulary (`gen_ai.*`, `cost.usd`, etc.) used across all GrayCodeAI repos.
See [rho/docs/OTEL-CONVENTIONS.md](https://github.com/GrayCodeAI/rho/blob/main/docs/OTEL-CONVENTIONS.md) for the shared OpenTelemetry attribute vocabulary (`gen_ai.*`, `cost.usd`, etc.) used across all GrayCodeAI repos.

## Build & Test

Expand Down Expand Up @@ -49,17 +49,17 @@ make ci # Full CI suite

## Common Pitfalls

- `engine`, `llm`, `graph` and `tools` are the host contract surface. Hawk
- `engine`, `llm`, `graph` and `tools` are the host contract surface. Rho
must not assemble `client`, `catalog`, `config`, `credentials`, `router` or
`runtime`. Six symbols Hawk needs (`ChatOptions`, `ContinuationConfig`,
`runtime`. Six symbols Rho needs (`ChatOptions`, `ContinuationConfig`,
`StreamResult`, `ResponseFormat`, `ImageURLPart`, `InputAudioPart`) live in
`llm` with no `engine` alias; widening the facade to cover them is a
deliberate API change, not an incidental one.
- `client.Provider` remains the lower-level compatibility boundary for other
consumers; preserve its method set and the facade's type identity
- Streaming tests need careful goroutine management
- `go.work` here should stay minimal; the parent `graycode-eco/go.work`
connects this independent `flux` checkout beside Hawk for local development.
connects this independent `flux` checkout beside Rho for local development.
Do not add extra local `replace` directives here without coordinating with
the parent workspace.

Expand Down Expand Up @@ -145,7 +145,7 @@ make ci # Full CI suite
| Main test file | `client/client_test.go` (httptest servers, provider detection) |
| Linter config | `.golangci.yml` (govet, ineffassign, misspell — minimal) |

This is an independent repository consumed by Hawk. In the local
`graycode-eco` parent workspace it is checked out beside `hawk` as `../flux`
This is an independent repository consumed by Rho. In the local
`graycode-eco` parent workspace it is checked out beside `rho` as `../flux`
and connected through the parent `go.work`; publish changes here, then update
Hawk's module pin through a separate PR.
Rho's module pin through a separate PR.
23 changes: 14 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,29 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · Versioning:

## [Unreleased]

### Changed
- **Renamed host product references from hawk to rho.** Host config paths
(`~/.rho/`), the `rho_build`/`rho_build_concise` tool namespaces, the
`rho_response` schema name, and the `EXPORT_RHO_FIXTURE` env var now use the
rho identity. Retired ecosystem repos (`shrike`, `harrier`, `kestrel`,
`merlin`) are no longer referenced.

## [0.0.1] — 2026-09-15

Reset to v0.0.1 for the rename to `flux`.

### Changed
- **Renamed the project from eyrie to flux.** Module path is now
- **Renamed the project to flux.** Module path is now
`github.com/GrayCodeAI/flux`. All packages, docs, SDK stubs, CI workflows,
and issue templates reference the new name; no Go API surface changed.
- **Logo redesigned** for the flux identity — abstract flow arcs around a
glowing bolt; the hawk/nest artwork is gone.
glowing bolt; the previous nest artwork is gone.
- **Makefile drops linker LDFLAGS.** flux is a library; the version is
embedded from the VERSION file, not injected into a main package.

Versions v0.3.0–v0.6.0 were published under the previous module paths
(`github.com/hawk/flux`, then `github.com/GrayCodeAI/eyrie`). They remain on
the Go module proxy under those old paths; new consumption starts at v0.0.1
of `github.com/GrayCodeAI/flux`.
Versions v0.3.0–v0.6.0 were published under the previous module paths. They
remain on the Go module proxy under those old paths; new consumption starts at
v0.0.1 of `github.com/GrayCodeAI/flux`.

### Changed — Shared MiMo auth-retry helper (2026-08-16)
- **Deduplicated `doRequestWithMimoAuthRetry`** between the OpenAI and
Expand Down Expand Up @@ -108,8 +114,7 @@ of `github.com/GrayCodeAI/flux`.
5. Whitespace collapse
Reports aggregate `BytesSaved` and `PercentOff` across all tools
in the slice. Safe to call concurrently.
Aligns flux with the rest of the hawk-eco ecosystem (`hawk`, `shrike`,
`harrier`, `kestrel`, `merlin`).
Aligns flux with the rest of the rho-eco ecosystem.

### Added
- Output guardrails framework (PII, secrets, injection, harmful content)
Expand Down Expand Up @@ -190,7 +195,7 @@ of `github.com/GrayCodeAI/flux`.

**Config**
- Provider detection from env vars (priority order)
- `~/.hawk/provider.json` config file I/O
- `~/.rho/provider.json` config file I/O
- `ApplyProviderConfigToEnv` — applies config to `os.Environ`
- OpenAI-compatible runtime resolution
- Provider profile management
Expand Down
2 changes: 1 addition & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/types/ @GrayCodeAI/llm-team
/catalog/ @GrayCodeAI/llm-team
/router/ @GrayCodeAI/llm-team
/flux.go @GrayCodeAI/llm-team
/version.go @GrayCodeAI/llm-team
/VERSION @GrayCodeAI/maintainers

# CI / release
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Thanks for your interest! This guide covers the conventions used across the
graycode-eco. The eco-wide standards (versioning, release tooling, repo layout)
are defined in <https://github.com/GrayCodeAI/hawk/blob/main/VERSIONING.md>.
are defined in <https://github.com/GrayCodeAI/rho/blob/main/VERSIONING.md>.

## Quick start

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 Hawk Contributors
Copyright (c) 2026 Rho Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Canonical hawk-eco Makefile for Go LIBRARY repos.
# flux is a versioned Go library consumed by Hawk (no standalone binary).
# Canonical rho-eco Makefile for Go LIBRARY repos.
# flux is a versioned Go library consumed by Rho (no standalone binary).

# ---------------------------------------------------------------------------
# Project metadata
Expand All @@ -8,7 +8,7 @@ NAME := flux

# ---------------------------------------------------------------------------
# Versioning — sourced from VERSION file; falls back to git describe.
# See https://github.com/GrayCodeAI/hawk/blob/main/VERSIONING.md.
# See https://github.com/GrayCodeAI/rho/blob/main/VERSIONING.md.
# ---------------------------------------------------------------------------
VERSION ?= $(shell cat VERSION 2>/dev/null | head -n1 | tr -d '[:space:]' || git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "none")
Expand Down Expand Up @@ -49,7 +49,7 @@ all: lint test build ## Default — lint, test, build.
# ---------------------------------------------------------------------------
# Build / install / release.
# ---------------------------------------------------------------------------
build: ## Build all library packages (flux is a library consumed by hawk; no standalone binary).
build: ## Build all library packages (flux is a library consumed by rho; no standalone binary).
go build ./...

# ---------------------------------------------------------------------------
Expand Down
25 changes: 11 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@

## What is flux

flux is the LLM provider runtime that powers the [hawk](https://github.com/GrayCodeAI/hawk) coding agent. It handles everything between your application and LLM APIs — authentication, model resolution, streaming, retries, rate limiting, and caching.
flux is the LLM provider runtime that powers the [rho](https://github.com/GrayCodeAI/rho) coding agent. It handles everything between your application and LLM APIs — authentication, model resolution, streaming, retries, rate limiting, and caching.

When your app calls a model, flux figures out which provider to use, how to talk to it, and how to stream the response back. Switch from Anthropic to Ollama? flux handles the translation. API returns 529? flux retries with backoff. Response hits `max_tokens`? flux continues automatically.

**Your app never talks to an LLM API directly. flux does.**

Hawk is the product face: it owns UX, agent orchestration, tools, permissions,
Rho is the product face: it owns UX, agent orchestration, tools, permissions,
sessions, and product semantics. Flux is the provider engine: it owns
credentials, catalog and route resolution, provider transports, normalized
streams, retry/fallback, usage, and provider telemetry. Hawk integrates through
streams, retry/fallback, usage, and provider telemetry. Rho integrates through
the stable [`engine`](engine/) facade rather than assembling Flux's internal
provider packages.

## Ecosystem Boundaries

flux is a Hawk support engine. Keep the dependency edge one-way.
flux is a Rho support engine. Keep the dependency edge one-way.

Hosts may import exactly four packages:

Expand All @@ -58,13 +58,12 @@ Hosts may import exactly four packages:

Everything else is engine-internal: `client`, `catalog`, `config`,
`credentials`, `router`, `runtime`, and their subpackages are not shared
contracts. Enforced by `hawk/scripts/check-flux-engine-boundary.sh`
and two Go AST tests in `hawk/internal/testaudit/`.
contracts. Enforced by `rho/scripts/check-flux-engine-boundary.sh`
and two Go AST tests in `rho/internal/testaudit/`.

- do not import `hawk/internal/*`
- do not import the removed legacy path `hawk/shared/types`
- do not import other engines (`harrier`, `shrike`, `swift`, `kestrel`,
`merlin`) — engines are peers, not dependencies
- do not import `rho/internal/*`
- do not import the removed legacy path `rho/shared/types`
- do not import other engines (`swift`) — engines are peers, not dependencies

## Quick Start

Expand Down Expand Up @@ -187,7 +186,7 @@ ANTHROPIC_API_KEY=sk-... go run ./examples/basic/

## Supported Providers

22 provider gateways in `catalog/registry/providers.go` (hawk `/config` uses the same list), listed in registry `SortOrder`:
22 provider gateways in `catalog/registry/providers.go` (rho `/config` uses the same list), listed in registry `SortOrder`:

| Provider | ID | Env variable |
|---|---|---|
Expand Down Expand Up @@ -319,10 +318,8 @@ flux is part of the graycode-eco:

| Component | Repository | Purpose |
|---|---|---|
| **hawk** | [GrayCodeAI/hawk](https://github.com/GrayCodeAI/hawk) | AI coding agent |
| **rho** | [GrayCodeAI/rho](https://github.com/GrayCodeAI/rho) | AI coding agent |
| **flux** | This repo | LLM provider runtime |
| **shrike** | [GrayCodeAI/shrike](https://github.com/GrayCodeAI/shrike) | Tokenizer & compression |
| **harrier** | [GrayCodeAI/harrier](https://github.com/GrayCodeAI/harrier) | Graph-based memory |
| **swift** | [GrayCodeAI/swift](https://github.com/GrayCodeAI/swift) | Session capture |

## Development
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ minor versions once `1.x` ships. Older versions receive critical-severity
fixes only on a best-effort basis.

The current canonical version is the contents of the [`VERSION`](./VERSION)
file at the repo root. See [`VERSIONING.md`](https://github.com/GrayCodeAI/hawk/blob/main/VERSIONING.md)
file at the repo root. See [`VERSIONING.md`](https://github.com/GrayCodeAI/rho/blob/main/VERSIONING.md)
for the eco-wide versioning scheme.

## Reporting a vulnerability

**Do not open a public GitHub issue for security vulnerabilities.** Instead:

1. Open a private [GitHub Security Advisory](https://github.com/GrayCodeAI/flux/security/advisories/new), **or**
2. Email `security@hawk.ai` with the details below.
2. Email `security@rho.ai` with the details below.

Include in your report:

Expand Down
2 changes: 1 addition & 1 deletion assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion catalog/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ func TestAnthropicNameToCanonical(t *testing.T) {
t.Parallel()
tests := []struct{ input, want string }{
{"claude-sonnet-4-6-20250814", "claude-sonnet-4-6"},
{"us.hawk.claude-opus-4-6-v1:0", "claude-opus-4-6"},
{"us.rho.claude-opus-4-6-v1:0", "claude-opus-4-6"},
{"claude-3-5-haiku-20241022", "claude-3-5-haiku"},
{"claude-3-7-sonnet-20250219", "claude-3-7-sonnet"},
{"claude-opus-4-5-20251101", "claude-opus-4-5"},
Expand Down
2 changes: 1 addition & 1 deletion catalog/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package catalog

// Credentials carries API keys and related env (base URLs) for provider-backed catalog discovery.
// Keys use standard env var names (e.g. OPENROUTER_API_KEY). Populate via config.DiscoveryCredentials.
// or pass an explicit map from hawk — do not hardcode provider lists in hawk.
// or pass an explicit map from rho — do not hardcode provider lists in rho.
type Credentials struct {
APIKeys map[string]string
}
Expand Down
2 changes: 1 addition & 1 deletion catalog/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package catalog
import "errors"

// ErrCatalogCacheRequired is returned when no valid ~/.flux/model_catalog.json exists.
// Run catalog discovery (hawk models refresh / flux catalog discover) to populate the cache.
// Run catalog discovery (rho models refresh / flux catalog discover) to populate the cache.
var ErrCatalogCacheRequired = errors.New("model catalog cache required")
2 changes: 1 addition & 1 deletion catalog/live/fetchers_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ func FetchConcentrate(env map[string]string) ([]Entry, error) {
// capabilities but omits the provider-level supports.tools field.
// The Responses API and model-details endpoint advertise function
// calling for these routed models, so preserve that capability for
// Hawk's tool-enabled coding loop.
// Rho's tool-enabled coding loop.
entry.Features = append(entry.Features, "function_calling")
entries = append(entries, entry)
}
Expand Down
2 changes: 1 addition & 1 deletion catalog/provider_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func apiKeyEnvFromDeployment(dep Deployment) string {
}

// CredentialStatusForProvider reports whether a provider needs an API key (local vs required).
// For set/empty status use hawk config.EnvKeyStatus or credentials.HasSecret — catalog does not read env.
// For set/empty status use rho config.EnvKeyStatus or credentials.HasSecret — catalog does not read env.
func CredentialStatusForProvider(compiled *CompiledCatalog, providerID string) string {
providerID = canonicalProviderID(providerID)
if providerID == "" {
Expand Down
2 changes: 1 addition & 1 deletion catalog/refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
// RefreshCatalog fetches the published catalog, validates it, and writes the cache.
// Unlike LoadCatalog with RefreshRemote, this fails when the remote fetch fails so
// callers never treat a stale cache as a successful refresh.
func RefreshCatalog(ctx context.Context, opts LoadCatalogOptions) (*RefreshResult, error) {

Check failure on line 53 in catalog/refresh.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: RefreshCatalog
if opts.CachePath == "" {
opts.CachePath = DefaultCachePath()
}
Expand Down Expand Up @@ -96,7 +96,7 @@
)
}

// DiscoverReport returns a multi-line report for `hawk models refresh` / `flux catalog discover`.
// DiscoverReport returns a multi-line report for `rho models refresh` / `flux catalog discover`.
func (r *RefreshResult) DiscoverReport() string {
if r == nil || r.Compiled == nil {
return "Catalog discovery: no data"
Expand Down
6 changes: 3 additions & 3 deletions catalog/registry/protocol_matrix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// agnes, kimi, openai, grok, openrouter, groq, canopywave, poolside,
// clinepass, ollama, azure, gemini (native/Gemini protocol), concentrate (Responses)
//
// Vendors documenting both OpenAI + Anthropic (hawk uses exactly one — OpenAI):
// Vendors documenting both OpenAI + Anthropic (rho uses exactly one — OpenAI):
// deepseek, zai_*, xiaomi_mimo_*, minimax_*, longcat
// opencodego keeps both clients only for per-model routing (one protocol per call;
// never cross-protocol fallback on the same request)
Expand All @@ -21,7 +21,7 @@ import (
// anthropic, bedrock
//
// Rule: if a vendor is OpenAI-compatible only, do not invent an Anthropic client.
// If a vendor documents both, hawk uses OpenAI only — never both protocols for the
// If a vendor documents both, rho uses OpenAI only — never both protocols for the
// same provider request (no OpenAI→Anthropic error fallback).

func TestProviderProtocolMatrix_OpenAIOnlyHaveNoAnthropicTransport(t *testing.T) {
Expand Down Expand Up @@ -50,7 +50,7 @@ func TestProviderProtocolMatrix_OpenAIOnlyHaveNoAnthropicTransport(t *testing.T)

func TestProviderProtocolMatrix_DualOfficialStayOpenAIPrimary(t *testing.T) {
t.Parallel()
// Catalog primary protocol is OpenAI chat completions. Hawk clients for these
// Catalog primary protocol is OpenAI chat completions. Rho clients for these
// providers use OpenAI only (OpenCode Go is the exception: per-model single
// protocol, still no cross-protocol fallback).
dualPrimaryOpenAI := []string{
Expand Down
2 changes: 1 addition & 1 deletion catalog/registry/provider_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestProviderSpecs_AgnesOpenAIOnlyLongCatOpenAIPrimary(t *testing.T) {
}

// LongCat: official docs expose BOTH OpenAI (/openai) and Anthropic (/anthropic).
// Hawk uses the OpenAI primary only — Anthropic is not required when OpenAI works.
// Rho uses the OpenAI primary only — Anthropic is not required when OpenAI works.
longcat, ok := registry.SpecByProviderID("longcat")
if !ok {
t.Fatal("missing longcat")
Expand Down
10 changes: 5 additions & 5 deletions catalog/testdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import (
"testing"
)

// Run with EXPORT_HAWK_FIXTURE=1 to refresh hawk/internal/catalogtest/testdata/minimal_v1.json
func TestExportHawkCatalogFixture(t *testing.T) {
// Run with EXPORT_RHO_FIXTURE=1 to refresh rho/internal/catalogtest/testdata/minimal_v1.json
func TestExportRhoCatalogFixture(t *testing.T) {
t.Parallel()
if os.Getenv("EXPORT_HAWK_FIXTURE") != "1" {
t.Skip("set EXPORT_HAWK_FIXTURE=1 to export") // TODO: https://github.com/GrayCodeAI/flux/issues/30
if os.Getenv("EXPORT_RHO_FIXTURE") != "1" {
t.Skip("set EXPORT_RHO_FIXTURE=1 to export") // TODO: https://github.com/GrayCodeAI/flux/issues/30
}
c := SeedCatalog()
data, err := json.MarshalIndent(c, "", " ")
if err != nil {
t.Fatal(err)
}
out := filepath.Join("..", "..", "hawk", "internal", "catalogtest", "testdata", "minimal_v1.json")
out := filepath.Join("..", "..", "rho", "internal", "catalogtest", "testdata", "minimal_v1.json")
if err := os.MkdirAll(filepath.Dir(out), 0o755); err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions catalog/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ func LoadCatalog(ctx context.Context, opts LoadCatalogOptions) (*CompiledCatalog
return compiled, nil
}
if opts.RequireCache {
return nil, fmt.Errorf("%w (%s missing or invalid; run: hawk models refresh)", ErrCatalogCacheRequired, opts.CachePath)
return nil, fmt.Errorf("%w (%s missing or invalid; run: rho models refresh)", ErrCatalogCacheRequired, opts.CachePath)
}
bootstrap := BootstrapCatalog()
compiled, err := CompileCatalog(&bootstrap)
Expand All @@ -639,7 +639,7 @@ func LoadCatalog(ctx context.Context, opts LoadCatalogOptions) (*CompiledCatalog
}
compiled.Diagnostics = append(compiled.Diagnostics, CatalogDiagnostic{
Code: "bootstrap_only",
Message: "no model catalog cache; run hawk models refresh or flux catalog discover",
Message: "no model catalog cache; run rho models refresh or flux catalog discover",
})
return compiled, nil
}
Expand Down
Loading
Loading