Skip to content

chore: sync submodule with origin/main - #96

Merged
Patel230 merged 31 commits into
mainfrom
feat/stepfun-merge-main-2
Jul 31, 2026
Merged

chore: sync submodule with origin/main#96
Patel230 merged 31 commits into
mainfrom
feat/stepfun-merge-main-2

Conversation

@Patel230

Copy link
Copy Markdown
Contributor

Syncs hawk/external/eyrie submodule with upstream, preserving 30 local commits.

Patel230 and others added 30 commits July 11, 2026 10:45
* Make all eyrie provider implementations uniform

- Gemini: add parseProviderError, SanitizeMessages, guardrails, request ID, Ping fix, 32MB limit
- Bedrock: add SanitizeMessages, guardrails, full buildBody forwarding, streaming usage fix, 30MB limit
- Azure: add guardrails, 30MB limit
- Vertex: pass requestID in StreamChat
- OpenAI: add 32MB size limit
- DeepSeek: replace string-based isRetryableError with structured EyrieError.IsRetriable()
- MiMo: update to structured errors, fix parseHTTPStatusFromError loop limit bug
- Z.AI: update to structured errors

* WIP: client package decomposition and provider uniformity work

* feat: add host-neutral engine facade

* feat: complete engine state and continuation support

* build: enforce host-neutral eyrie boundary

* feat: complete engine generation contract

* fix: list models by serving gateway

* fix: preserve credential save reassurance

* feat: expose engine selection lifecycle

* fix: preserve model-only selection compatibility

* feat: move native compaction behind engine

* feat: expose provider control plane

* feat: expose effective engine selection

* fix: require configured local gateway

* feat: complete host model metadata

* feat: expose host-neutral model policy

* fix: preserve deterministic model metadata

* feat: expose host control diagnostics

* feat: report complete catalog health

* fix: expose credential env aliases

* feat: complete host control facade

* feat: close engine runtime boundary

* feat: harden host engine boundary

* refactor: enforce client adapter layering
The shared workflow template pinned trufflesecurity/trufflehog to a
commit SHA labeled "main 2026-05-18" — a floating branch reference
disguised as a pin, not an actual release. Repins to v3.95.9, the
current real trufflehog release. Companion fix to GrayCodeAI/hawk#96,
which fixes the same issue at the template source.
… remove log truncation (#67)

Removing '| head -50' on deadcode/jscpd output was hiding failures past line 50.
Pinning actions/checkout, actions/setup-node, docker/* actions to SHA digests
guards against tag-mutation supply-chain attacks.
…69)

* docs: correct the provider table — 12 of 22 shipped providers were documented

Also fixed a stale ID: the Z.AI row listed z-ai, which doesn't exist in the
registry (the real IDs are zai_coding and zai_payg, two separate providers).
Rewrote the full table from catalog/registry/providers.go directly —
deepseek, the zai/minimax split, azure, bedrock, vertex, poolside, groq,
and clinepass were all missing.

* fix(eyrie): stop falling back to OPENAI base URL for other providers

A stray OPENAI_BASE_URL / OPENAI_API_BASE in the host environment would
send a non-OpenAI provider's API key to whatever host that var points
at, because 17 providers and 16 runtime profiles ended their BaseURLEnv
lookup chain on the OpenAI vars.

Trim OPENAI_BASE_URL and OPENAI_API_BASE out of every non-OpenAI
provider's BaseURLEnv slice in catalog/registry/providers.go and every
non-OpenAI runtime profile in config/profiles.go. A provider's base URL
must come only from its own env vars. Added a regression test asserting
anthropic no longer resolves through the OpenAI vars.
- Added failingStore mock type for deterministic credential fail testing
- TestPreflight_NotReady_WhenCredentialsFail now uses failing store
- TestPreflight_MultipleFailures now uses failing store
- Eliminates environment-dependent test skips
* fix(eyrie): Bedrock secret masking, streaming context cancel, HTTP header injection fix, SQLite perms

SECURITY FIXES:
- Change secretAccessKey from string to []byte to prevent accidental logging
- Add String() method to BedrockClient that masks secrets
- Add context cancellation for Bedrock streaming EventStreamReader

BUG FIXES:
- Fix storage/sqlite.go chmod failure on :memory: databases

SECURITY HARDENING:
- Extend control character rejection in custom headers from \r\n to all chars < 0x20
- Add circuit breaker field to Router for future use

* fix: gofmt formatting

* fix: remove unused breakers field
* Graphify integration: AGENTS.md + CLAUDE.md

* fix: demote GitNexus heading to H2 (markdownlint MD025)
)

* defaults: host-neutral ServiceName and config-dir (was hardcoded 'hawk')

ServiceName defaults to 'eyrie' (host-neutral); embedders call
SetServiceName before any credential access. Config-dir default
renamed from 'hawk' to 'eyrie'. Engine API unchanged.

* feat: improve provider catalog and credential handling

* feat: migrate legacy provider.json from old 'hawk' config dir

When the default config dir was renamed from 'hawk' to 'eyrie', an existing
provider.json in the old dir was silently ignored — upgrading users lost
their provider/model selection, deployments, and routing.

On first engine start, if the eyrie-dir provider.json does not yet exist,
copy it from <UserConfigDir>/hawk/provider.json. One-time, idempotent,
never overwrites newer state.

* feat: migrate legacy categories.json + fix categories override dir

loadOverrides now reads categories.json from the host-neutral eyrie dir
(EYRIE_CONFIG_DIR → HAWK_CONFIG_DIR compat → <userdir>/eyrie) to match
GetProviderConfigDir, instead of hardcoding the old hawk dir.

The one-time legacy_config migration now also copies categories.json from
<userdir>/hawk to <userdir>/eyrie on upgrade, alongside provider.json.

* docs: remove GitNexus references from AGENTS.md, delete CLAUDE.md

GitNexus docs superseded by Graphify integration (PR #72).

* ci: retrigger
* feat(client): alias client/core DTOs to hawk-core-contracts/llm

Conversation DTOs (EyrieMessage, EyrieResponse, ChatOptions, ...)
and StreamResult are now type aliases of the canonical port contract.
client/core becomes a pure leaf alias layer; the names still re-export
through client/aliases.go so the public client API is unchanged.

StreamResult's Close() and constructors now resolve to the contract's
single canonical NewStreamResult(events, requestID, cancel); all
call sites updated. GLMThinkingEnabled added to the contract's
ChatOptions so the Z.ai toggle hawk sets / OpenAI adapter reads lives
in one place.

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(engine): alias conversation DTOs to canonical contract

The engine facade's conversation types (Message, ContentPart, Tool,
Usage, GenerateResponse, Event, ...) now alias hawk-core-contracts/llm,
the same definitions hawk and the client already alias. Field names
conform to the contract: ToolCalls->ToolUse, flat ContentPart->nested,
InputTokens/OutputTokens->PromptTokens/CompletionTokens,
TTFTMillis->TTFTms, EventType enum->plain string constants.

engine/convert.go collapses: toClientMessages/fromClientUsage are now
identity (both sides speak the contract); fromClientResponse only sets
the resolved route. Intent/ModelClass alias the contract enums.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(config): GetProviderConfigDir returns error instead of panicking

GetProviderConfigDir previously panic()d when os.UserConfigDir() failed
(e.g. containers/CI with unset HOME). Return (string, error) instead and
propagate through GetProviderConfigPath. All 12 callers updated to fall
back gracefully (empty path) or surface the error — never panic.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: refund rate limiter token on context cancellation

- Add token refund in wait() when context is cancelled during min-interval
- Change GetProviderConfigDir() to return (string, error) instead of panicking
- Update callers to handle new error return
- Add test coverage for error paths

* feat: add nil transport guard, CatalogSnapshot alias, token refund

- Guard against nil transport in resolveProvider
- Alias CatalogSnapshot to llm.CatalogSnapshot
- Refund rate limiter token on context cancellation

---------

Co-authored-by: Claude <noreply@anthropic.com>
- Add token refund in wait() when context is cancelled during min-interval
- Change GetProviderConfigDir() to return (string, error) instead of panicking
- Update callers to handle new error return
- Add test coverage for error paths
* fix(eyrie): make legacy config migration correct and atomic

The migration I added in b2cab57 (PR #77) had three real bugs:

1. Read source + dest directly from os.UserConfigDir(), ignoring
   EYRIE_CONFIG_DIR / HAWK_CONFIG_DIR. A host using a custom
   EYRIE_CONFIG_DIR ended up with the legacy file copied to a path
   eyrie never reads — the migration was effectively a no-op for
   that user, and silently wrote to an invisible location.

2. Swallowed MkdirAll / WriteFile errors with '_ ='. On a partial
   write or read-only filesystem the destination provider.json could
   be left corrupt / empty, and the next start looks like a fresh
   install. Now slog.Warn on each failure (best-effort, non-fatal).

3. TOCTOU between os.Stat and os.WriteFile. Two engines starting in
   parallel could both miss the file, both write, and race on
   contents. Now uses .tmp + os.Rename for an atomic swap, so a
   concurrent engine cannot observe a half-written file.

Source + destination now both derived from config.GetProviderConfigDir(),
so the migration honors the same env-var resolution as the rest of
eyrie. Added tests covering EYRIE_CONFIG_DIR redirection and the
atomic-write + idempotency invariants.

* fix(eyrie): return error from GetProviderConfigDir; fix goroutine leak in adaptive rate limiter

Two real bugs:

1. GetProviderConfigDir panicked with 'user config directory unavailable'
   on platforms where os.UserConfigDir fails (sandboxed runtimes,
   restricted $HOME). It now returns (string, error) so callers can
   recover; a MustGetProviderConfigDir shim is provided for startup
   paths that genuinely cannot proceed. Updated all 6 production
   call sites in runtime/, setup/, engine/ and the 2 test files.

2. AdaptiveRateLimitProvider.StreamChat wrapped the inner stream's
   events channel in a goroutine that blocked on
   'wrappedCh <- evt' forever if the caller's ctx was cancelled.
   The goroutine never observed ctx.Done, never released the
   inner stream's body, and the caller waited indefinitely. Now
   selects on ctx.Done and calls result.Close() to release the
   inner stream, then drains remaining events so the inner parser
   can complete cleanly.

* fix(eyrie): M1-M6 MEDIUM hardening

- retry: return a clear error if a request body is set but GetBody is
  nil, instead of silently retrying a drained body.
- conversation: emit EventError before EventDone when a continuation
  request fails, so truncated responses aren't indistinguishable from
  clean completions.
- coalesce: replace time.Sleep with a cancellable timer that exits on
  ctx.Done, so the cleanup goroutine doesn't linger for the full TTL
  on shutdown.
- config: delete the exported-but-unused ValidateBaseURL (only test
  caller removed).
- adaptive_ratelimit: audit confirmed recordTokens + shared-window
  mutations already take a.mu — no code change; documented lock
  invariant.

* chore(eyrie): centralize magic numbers in client/core/constants.go

Retry defaults, transport timeouts and cooldown windows now reference
named constants. DefaultRetryConfig uses them. Deferred: full split of
the 215-line providerSpecs() literal and the batch.go inline retry
(LOW effort, mechanical).
* fix: vet DefaultPaths test signature, markdown table pipe style

* fix(ci): clone hawk-core-contracts dep, add -test flag to deadcode

* fix(lint): sloppyReassign, S1016, S1011 in engine and config

* fix(test): clear XDG_CONFIG_HOME so os.UserConfigDir() uses /Users/lakshmanpatel override

* fix(ci): clone ecosystem deps for fuzz job too
Re-export host-facing DTOs from hawk-core-contracts/llm, assert *Engine
implements llm.Provider and *Stream implements EventStreamer, return
EventStreamer from Stream with proper nil-interface handling, and document
the llm dependency on the ecosystem boundary.
* fix(engine): implement llm.Provider via contract aliases

Re-export host-facing DTOs from hawk-core-contracts/llm, assert *Engine
implements llm.Provider and *Stream implements EventStreamer, return
EventStreamer from Stream with proper nil-interface handling, and document
the llm dependency on the ecosystem boundary.

* fix(deps): pin hawk-core-contracts to llm host-port alignment

CI resolves modules without go.work; pin the feature commit that provides
EventStreamer, CheckStatus, and the aligned CatalogHealth/Preflight types.

* fix(deps): pin hawk-core-contracts to main after #16 merge

Use the published main tip so CI can resolve EventStreamer and aligned
host types without feature-branch pseudo-version unshallow issues.

* fix(deps): pin hawk-core-contracts to v0.1.8

Use the tagged host-port alignment release so CI avoids pseudo-version
unshallow failures.
…ess) (#89)

* fix(engine): implement llm.Provider via contract aliases

Re-export host-facing DTOs from hawk-core-contracts/llm, assert *Engine
implements llm.Provider and *Stream implements EventStreamer, return
EventStreamer from Stream with proper nil-interface handling, and document
the llm dependency on the ecosystem boundary.

* fix(deps): pin hawk-core-contracts to llm host-port alignment

CI resolves modules without go.work; pin the feature commit that provides
EventStreamer, CheckStatus, and the aligned CatalogHealth/Preflight types.

* fix(deps): pin hawk-core-contracts to main after #16 merge

Use the published main tip so CI can resolve EventStreamer and aligned
host types without feature-branch pseudo-version unshallow issues.

* fix(deps): pin hawk-core-contracts to v0.1.8

Use the tagged host-port alignment release so CI avoids pseudo-version
unshallow failures.

* fix(client): export cache type, propagate stream Close, error on empty fallback

- Export AnthropicCachedMessage (was unexported anthropicCachedMessage),
  fixing golint/revive violation of exported func returning unexported type
- Propagate inner stream Close/cancel in AdaptiveRateLimitProvider.StreamChat
  and CallbackProvider.StreamChat to prevent connection leaks on normal drain
- Change NewFallbackProvider to return (*FallbackProvider, error) instead of
  returning nil on empty input, eliminating a nil-provider footgun

* feat(engine): wire rate limiting and caching into the engine facade

Add opt-in EnableRateLimiting and EnableCaching options to engine.Options.
When enabled, the defaultTransport wraps the resolved provider with
AdaptiveRateLimitProvider (outermost) and CachedProvider, closing the gap
between advertised features and actual facade behavior. Both are off by
default to preserve backward compatibility.

* fix(engine,credentials): improve IntentFast heuristic, replace context.TODO

- IntentFast now sorts by ContextWindow ascending (better latency proxy)
  with MaxOutput as secondary tiebreaker, instead of MaxOutput alone
- Replace context.TODO() with context.Background() in credential lookup
  and health checks — TODO is for placeholder code, Background is correct
  when no caller context is available

* feat(client): add per-provider timeout to fallback chain; document secret cache

- Add PerProviderTimeout field to FallbackProvider that bounds each
  individual Chat attempt, preventing a hung provider from blocking the
  entire chain until the caller's context expires
- Document the plaintext secret caching tradeoff in CombinedStore with
  threat model rationale and mitigation guidance

* refactor(catalog): centralize model alias resolution into ResolveModel helper

Extract the trim + nil-check + fallback-to-native pattern that was
duplicated across router/preview.go, engine/host_control.go, and
runtime/selection.go into a single catalog.ResolveModel function.
Callers now delegate to this helper instead of reimplementing the
same logic.

* test(catalog): add ResolveModel edge-case tests

Covers direct ID, alias, not-found, nil catalog (native ID + alias),
empty string, and whitespace trimming.

* feat(engine): add JSON tags to Error struct for machine-readable errors

The Error struct now serializes to JSON with code, operation, provider,
model, message, and retryable fields. The Cause field is excluded from
JSON (json:"-") since it is an error interface that cannot be reliably
serialized.

* test(engine): add convert tests and conversation continuation tests

- Add engine/convert_test.go: 15 tests for toClientMessages, toClientOptions,
  fromClientResponse, fromClientUsage, setMetadataIfPresent, cloneStringMap
- Add conversation continuation test: verifies streamAndSave continues on
  max_tokens and emits a single done event
- Add context-cancellation test: verifies the events channel closes
  promptly when the context is cancelled (no stream leak)

* test: add coverage for gateway pure functions (SetupGatewayID, CatalogProviderID, CredentialEnvKeys, GatewayStatuses, normalizeRuntimeProviderID)

* feat: add execution graph module

- Add engine/graph.go with execution graph implementation
- Add engine/graph_test.go with test coverage
- Update README

* feat: enhance operations graph

- Add OperationsGraph implementation
- Support node and edge management
- Add serialization to portable GraphSpec
Incorporates StepFun provider (stepfun.ai) from origin/main while preserving
29 local commits for ecosystem architecture, engine contracts, and fixes.
@Patel230
Patel230 merged commit b766784 into main Jul 31, 2026
3 of 7 checks passed
@Patel230
Patel230 deleted the feat/stepfun-merge-main-2 branch July 31, 2026 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant