Skip to content

Commit 82c7df7

Browse files
authored
feat(providers): add native Nous Portal provider (Codex-style OAuth, no hermes_cli dep) (#2102)
* feat(providers): add native Nous Portal provider (codex-style OAuth, no hermes_cli dep) Adds a 'nous' provider that speaks the OpenAI-compatible wire format (thin subclass of OpenAICompatibleLLM) and authenticates with the rotating, inference-scoped JWT from a 'hermes portal' login — read natively from ~/.hermes/auth.json, exactly mirroring the Codex provider. No dependency on the hermes_cli package. - nous_auth.py: NousAuthManager reads providers.nous OAuth state, decodes the JWT exp for proactive refresh, and refreshes via POST {portal}/api/oauth/token (x-nous-refresh-token header). Atomic write-back of rotated tokens. Because the Hermes auth store is shared with a possibly-running Hermes agent, refresh takes the same ~/.hermes/auth.lock flock Hermes uses and re-reads the latest refresh_token from disk before exchange (single-use RT reuse-detection safety). - nous_llm.py: thin subclass; proactive refresh offloaded to a thread so the event loop never blocks; one reactive refresh + retry on a 401. - llm_wrapper.py: register nous in dispatch, validator, no-key set, base-url default. - tests: auth-store load/refresh/persist/terminal-error + provider wiring (no Hermes install or network needed). * docs(providers): document nous provider + add default model - config.py: add nous to PROVIDER_DEFAULT_MODELS (deepseek/deepseek-v4-flash) so omitting HINDSIGHT_API_LLM_MODEL doesn't fall back to gpt-4o-mini. - configuration.md: add nous to the provider list + an env example block. - models.mdx: add a nous example + a 'Nous Portal Setup (Hermes)' section covering the 'hermes portal' login, the no-API-key flow, and automatic JWT refresh that coordinates with a running Hermes agent. - skills/hindsight-docs: regenerated bundle from the docs sources.
1 parent a0e6bed commit 82c7df7

10 files changed

Lines changed: 1121 additions & 2 deletions

File tree

hindsight-api-slim/hindsight_api/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ def normalize_config_dict(config: dict[str, Any]) -> dict[str, Any]:
596596
"volcano": "doubao-pro-32k",
597597
"openrouter": "qwen/qwen3.5-9b",
598598
"fireworks": "accounts/fireworks/models/llama-v3p1-8b-instruct",
599+
"nous": "deepseek/deepseek-v4-flash",
599600
}
600601
DEFAULT_LLM_MODEL = "gpt-4o-mini" # Fallback if provider not in table
601602
# Built-in llama.cpp defaults

hindsight-api-slim/hindsight_api/engine/llm_wrapper.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ def parse_llm_json(raw: str) -> Any:
232232
"litellm",
233233
"litellmrouter",
234234
"bedrock",
235+
"nous",
235236
}
236237
)
237238

@@ -437,6 +438,21 @@ def create_llm_provider(
437438
extra_body=extra_body,
438439
)
439440

441+
elif provider_lower == "nous":
442+
# Nous Portal is OpenAI-compatible on the wire; NousLLM adds rotating
443+
# inference:invoke JWT auth read natively from ~/.hermes/auth.json
444+
# (no static api_key, no hermes_cli dependency — same shape as Codex).
445+
from hindsight_api.engine.providers.nous_llm import NousLLM
446+
447+
return NousLLM(
448+
provider=provider,
449+
api_key=api_key,
450+
base_url=base_url,
451+
model=model,
452+
reasoning_effort=reasoning_effort,
453+
extra_body=extra_body,
454+
)
455+
440456
elif provider_lower in (
441457
"openai",
442458
"groq",
@@ -569,6 +585,7 @@ def __init__(
569585
"zai",
570586
"opencode-go",
571587
"fireworks",
588+
"nous",
572589
]
573590
if self.provider not in valid_providers:
574591
raise ValueError(f"Invalid LLM provider: {self.provider}. Must be one of: {', '.join(valid_providers)}")
@@ -593,6 +610,8 @@ def __init__(
593610
self.base_url = "https://api.z.ai/api/coding/paas/v4"
594611
elif self.provider == "opencode-go":
595612
self.base_url = "https://opencode.ai/zen/go/v1"
613+
elif self.provider == "nous":
614+
self.base_url = "https://inference-api.nousresearch.com/v1"
596615

597616
# Prepare Vertex AI config (if applicable)
598617
vertexai_project_id = None

0 commit comments

Comments
 (0)