Skip to content
Closed
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
39 changes: 23 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ env:
GOPRIVATE: "github.com/GrayCodeAI/*"
GONOSUMDB: "github.com/GrayCodeAI/*"
GONOSUMCHECK: "1"
# CI must resolve the module versions pinned in go.mod/go.sum, not whatever
# sibling working trees a go.work workspace happens to point at. Go's own
# reference warns a committed go.work "may cause a continuous integration (CI)
# system to select and thus test the wrong versions of a module's
# dependencies" and that "CI systems should generally not be allowed to use
# the go.work file".
GOWORK: "off"

jobs:
# -------------------------------------------------------------------------
Expand Down Expand Up @@ -74,8 +81,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: go mod tidy
run: |
go mod tidy
Expand Down Expand Up @@ -108,8 +115,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: go vet
run: go vet ./...

Expand All @@ -128,8 +135,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: Boundary guard
run: |
bash ./scripts/check-ecosystem-boundaries.sh
Expand All @@ -154,8 +161,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: Boundary guard
run: |
bash ./scripts/check-ecosystem-boundaries.sh
Expand Down Expand Up @@ -195,8 +202,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@v1.1.4
Expand All @@ -220,8 +227,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: deadcode
run: |
go install golang.org/x/tools/cmd/deadcode@v0.30.0
Expand Down Expand Up @@ -283,8 +290,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: Run fuzz targets
run: |
go test -fuzz=FuzzSanitizeMessages -fuzztime=60s ./client
Expand Down Expand Up @@ -315,8 +322,8 @@ jobs:
cache: true
- name: Clone ecosystem deps
run: |
git clone --depth=1 https://github.com/GrayCodeAI/tok.git ../tok
git clone --depth=1 https://github.com/GrayCodeAI/hawk-core-contracts.git ../hawk-core-contracts
git clone --depth=1 https://github.com/GrayCodeAI/shrike.git ../shrike
git clone --depth=1 https://github.com/GrayCodeAI/eagle.git ../eagle
- name: Build (library — cross-compile all packages)
env:
GOOS: ${{ matrix.goos }}
Expand Down
10 changes: 8 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ make ci # Full CI suite
- `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; hawk's own `go.work` adds an `external/eyrie` replace so hawk can develop against a local eyrie checkout. Do not add extra local `replace` directives here without coordinating with hawk's workspace.
- `go.work` here should stay minimal; the parent `graycode-eco/go.work`
connects this independent `eyrie` checkout beside Hawk for local development.
Do not add extra local `replace` directives here without coordinating with
the parent workspace.

## Naming Conventions

Expand Down Expand Up @@ -138,4 +141,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 repo is a submodule of [hawk](https://github.com/GrayCodeAI/hawk) at `hawk/external/eyrie`. Work in the submodule (go.work picks it up), push, sync here, PR/merge, then pull main in the submodule.
This is an independent repository consumed by Hawk. In the local
`graycode-eco` parent workspace it is checked out beside `hawk` as `../eyrie`
and connected through the parent `go.work`; publish changes here, then update
Hawk's module pin through a separate PR.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · Versioning:
5. Whitespace collapse
Reports aggregate `BytesSaved` and `PercentOff` across all tools
in the slice. Safe to call concurrently.
Aligns eyrie with the rest of the hawk-eco ecosystem (`hawk`, `tok`,
`yaad`, `sight`, `inspect`).
Aligns eyrie with the rest of the hawk-eco ecosystem (`hawk`, `shrike`,
`harrier`, `kestrel`, `merlin`).

### Added
- Output guardrails framework (PII, secrets, injection, harmful content)
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ provider packages.

eyrie is a Hawk support engine. Keep the dependency edge one-way:

- host-facing DTOs and the `Provider` port live in `hawk-core-contracts/llm`; `engine/` re-exports them as aliases (`*Engine` implements `llm.Provider`)
- host-facing DTOs and the `Provider` port live in `eagle/llm`; `engine/` re-exports them as aliases (`*Engine` implements `llm.Provider`)
- internal provider/transport types stay eyrie-scoped (not shared contracts)
- do not import `hawk/internal/*`
- do not import removed legacy path `hawk/shared/types`
- do not import other engines (`yaad`, `tok`, `trace`, `sight`, `inspect`) — engines are peers, not dependencies
- do not import other engines (`harrier`, `shrike`, `swift`, `kestrel`, `merlin`) — engines are peers, not dependencies

## Quick Start

Expand Down Expand Up @@ -308,9 +308,9 @@ eyrie is part of the hawk-eco:
|---|---|---|
| **hawk** | [GrayCodeAI/hawk](https://github.com/GrayCodeAI/hawk) | AI coding agent |
| **eyrie** | This repo | LLM provider runtime |
| **tok** | [GrayCodeAI/tok](https://github.com/GrayCodeAI/tok) | Tokenizer & compression |
| **yaad** | [GrayCodeAI/yaad](https://github.com/GrayCodeAI/yaad) | Graph-based memory |
| **trace** | [GrayCodeAI/trace](https://github.com/GrayCodeAI/trace) | Session capture |
| **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
2 changes: 1 addition & 1 deletion client/adapters/anthropic.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"net/http"
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// maxAnthropicRequestSize is the maximum request body size for the Messages API (32 MB).
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/anthropic_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package adapters
import (
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// AnthropicBaseFromOpenAIV1 strips a trailing /v1 from an OpenAI-compatible base URL.
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"net/http"
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/bedrock.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
"strings"
"time"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/concentrate_responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"strings"
"time"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// ConcentrateResponsesClient uses the Concentrate Responses API (the production-ready
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/gemini.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"os"
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// geminiSharedParserEnvVar is the opt-out flag for the new
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/openai.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"net/http"
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/protocol_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"fmt"
"strings"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// ChatProtocol selects which existing eyrie client handles a gateway request.
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/protocol_router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http"
"testing"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

func TestNewStreamWithReasoningFallbackChatFirst(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion client/adapters/vertex.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"log/slog"
"net/http"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// maxVertexRequestSize is the maximum request body size for Vertex AI (30 MB).
Expand Down
4 changes: 2 additions & 2 deletions client/aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"net/http"
"time"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/adapters"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/eyrie/client/embeddings"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// The provider contract and request/response data types live in
Expand Down Expand Up @@ -88,7 +88,7 @@
)

// NewStreamGuardrails builds an incremental guardrail scanner over a rule set.
func NewStreamGuardrails(g *Guardrails, config StreamGuardrailConfig) *StreamGuardrails {

Check failure on line 91 in client/aliases.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: NewStreamGuardrails
return core.NewStreamGuardrails(g, config)
}

Expand Down Expand Up @@ -234,7 +234,7 @@
// NewStreamResult creates a StreamResult with a cancel function for resource
// cleanup. The request ID is optional; pass "" when it is not yet available.
// The canonical constructor lives in
// github.com/GrayCodeAI/hawk-core-contracts/llm; this is a thin facade
// github.com/GrayCodeAI/eagle/llm; this is a thin facade
// wrapper that keeps the public client API stable.
func NewStreamResult(events <-chan EyrieStreamEvent, cancel context.CancelFunc) *StreamResult {
return llm.NewStreamResult(events, "", cancel)
Expand Down
6 changes: 3 additions & 3 deletions client/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// core is a leaf package — it must not import any other eyrie/client
// subpackage. The conversation DTOs below are aliases to the canonical
// hawk-core-contracts/llm definitions; core re-exports them so subpackages
// eagle/llm definitions; core re-exports them so subpackages
// share the contract without an import cycle through the facade. The public
// names remain available as aliases in github.com/GrayCodeAI/eyrie/client,
// which is the API consumers should keep importing.
Expand All @@ -15,7 +15,7 @@ package core
import (
"context"

"github.com/GrayCodeAI/hawk-core-contracts/llm"
"github.com/GrayCodeAI/eagle/llm"
)

// Provider is the core interface for LLM providers.
Expand Down Expand Up @@ -76,7 +76,7 @@ type EyrieStreamEvent = llm.EyrieStreamEvent
//
// StreamResult is aliased to the canonical contract type; its Close()
// method and canonical constructor (NewStreamResult) live in
// github.com/GrayCodeAI/hawk-core-contracts/llm.
// github.com/GrayCodeAI/eagle/llm.
type StreamResult = llm.StreamResult

// ResponseFormat specifies the desired output format for the model response.
Expand Down
2 changes: 1 addition & 1 deletion client/embeddings/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"sync"
"testing"

"github.com/GrayCodeAI/eagle/llm"
"github.com/GrayCodeAI/eyrie/client/core"
"github.com/GrayCodeAI/hawk-core-contracts/llm"
)

// echoMock is a minimal core.Provider that echoes the last user message and
Expand Down
2 changes: 1 addition & 1 deletion client/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Rules:

// ExtractRelationships extracts subject-predicate-object triples from text using
// schema-validated structured output with retry. It is a typed convenience layer
// over ChatWithStructuredOutput, modeled on CocoIndex's ExtractByLlm; yaad and
// over ChatWithStructuredOutput, modeled on CocoIndex's ExtractByLlm; Harrier and
// other knowledge-graph consumers can call it instead of hand-rolling extraction
// prompts and JSON parsing.
func (c *EyrieClient) ExtractRelationships(ctx context.Context, text string, opts ExtractOptions) ([]Relationship, error) {
Expand Down
2 changes: 1 addition & 1 deletion client/token_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func fallbackTokenCount(text string) int {
}

// compressForSummary keeps PromptOptimizer self-contained. It performs a small
// whitespace-normalizing reduction instead of depending on tok's full pipeline.
// whitespace-normalizing reduction instead of depending on shrike's full pipeline.
func compressForSummary(text string) string {
text = strings.TrimSpace(text)
if text == "" {
Expand Down
1 change: 1 addition & 0 deletions config/discovery_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func (emptyCredentialStore) Get(context.Context, string) (string, error) { retur
func (emptyCredentialStore) Delete(context.Context, string) error { return nil }

func TestHasAnyConfiguredDeployment_RejectsPlaceholder(t *testing.T) {
t.Setenv("HAWK_CONFIG_DIR", t.TempDir())
credentials.SetDefaultStore(emptyCredentialStore{})
t.Cleanup(func() { credentials.SetDefaultStore(nil) })

Expand Down
13 changes: 7 additions & 6 deletions docs/architecture/HOST-ENGINE-BOUNDARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,22 +169,23 @@ Preflight has two explicit modes:
These modes must not be conflated: local readiness is suitable for startup and
diagnostics; live readiness is an explicit network operation.

## Release and submodule order
## Release and sibling-repository order

The boundary is delivered Eyrie-first:

```text
1. Change and verify standalone Eyrie
2. Commit Eyrie and publish a resolvable release/commit
3. Update Hawk's Eyrie module version when required
4. Advance Hawk's Eyrie submodule pin to that exact commit
4. Update Hawk's Eyrie module pin to that exact published commit
5. Verify Hawk integration, boundary checks, and clean-clone/module builds
6. Commit Hawk's code and gitlink update together
6. Commit the Hawk module-pin update in Hawk's repository
```

Hawk must never point at an uncommitted Eyrie worktree. A submodule pin proves
source identity; a resolvable module version is also required for workflows
that build Hawk with `GOWORK=off`.
Hawk must never depend on an uncommitted Eyrie worktree. The parent workspace
uses a sibling checkout for source identity during local development; a
resolvable published module version is also required for workflows that build
Hawk with `GOWORK=off`.

## Compatibility policy

Expand Down
2 changes: 1 addition & 1 deletion docs/design/EYRIE-ENTERPRISE.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ These repos are privacy-first; the enterprise layer must not regress that.

1. **Single-tenant per binary vs. multi-org per binary?** This doc assumes multi-org within one
operator's deployment. Is true cross-customer multi-tenancy ever in scope, or does that stay
a hawk-cloud concern (`TOP20_COMPARISON.md:33-34`)?
a graycode-cloud concern (`TOP20_COMPARISON.md:33-34`)?
2. **SSO scope:** OIDC only for P0, or do enterprise buyers require SAML (which needs a heavier
dep)? SAML likely pushes to P2.
3. **Where does `session_id` originate?** From the OpenAI `user` field (`openai_proxy.go:41`), a
Expand Down
Loading
Loading