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
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,17 @@ It configures Hermes to use:
- `provider: custom`
- `https://api.gonkagate.com/v1`

Your GonkaGate key is stored only in `~/.hermes/.env`. It is never written to
`config.yaml`.
Your raw GonkaGate key is stored only in `~/.hermes/.env`. It is never written
to `config.yaml`; the config only stores the `${GONKAGATE_API_KEY}` reference
Hermes needs for the custom endpoint.

When setup succeeds, the helper writes only the GonkaGate-managed surface:

- `model.provider`
- `model.base_url`
- `model.default`
- `OPENAI_API_KEY`
- `model.api_key = ${GONKAGATE_API_KEY}`
- `GONKAGATE_API_KEY`

## Important Limits

Expand Down
13 changes: 7 additions & 6 deletions docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,24 @@ Today the repository ships:
7. Pick one qualified live model. Interactive mode keeps the model picker
visible; single-option flows may auto-select that one qualified model.
8. Build one deterministic pre-write review that includes planned config
changes and takeover confirmations. Legacy endpoint paths are not cleaned or
changes and blocking conflicts. Legacy endpoint paths are not cleaned or
migrated by the helper.
9. Create same-run backups, write `config.yaml` first, write `.env` second,
and roll back `config.yaml` by pre-run state if the later `.env` write
fails.
10. Print the final summary, including target paths, applied cleanup, and the
reminder that `/v1/models` proved auth and catalog visibility only.
optional one-command Hermes smoke test. The summary still reminds users
that `/v1/models` proved auth and catalog visibility only.

## Product Boundaries

The helper intentionally stays narrow:

- it owns the GonkaGate onboarding path, not general Hermes bootstrap
- it manages only `model.provider`, `model.base_url`, `model.default`, and
`OPENAI_API_KEY`, plus current `model.api_key`, `model.api`, and
incompatible `model.api_mode` cleanup when those compete with the managed
main endpoint
- it manages only `model.provider`, `model.base_url`, `model.default`,
`model.api_key = ${GONKAGATE_API_KEY}`, and `.env` `GONKAGATE_API_KEY`,
plus current `model.api` and incompatible `model.api_mode` cleanup when
those compete with the managed main endpoint
- it does not mutate `auth.json` credential pools
- it does not mutate shell profiles
- it does not accept arbitrary custom base URLs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ model:
provider: custom
base_url: https://api.gonkagate.com/v1
default: minimaxai/minimax-m2.7
api_key: ${GONKAGATE_API_KEY}
```

## Sanitized Env Shape

```dotenv
OPENAI_API_KEY=[REDACTED]
GONKAGATE_API_KEY=[REDACTED]
```

## Basic Text Turn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ model:
provider: custom
base_url: https://api.gonkagate.com/v1
default: moonshotai/kimi-k2.6
api_key: ${GONKAGATE_API_KEY}
```

## Sanitized Env Shape

```dotenv
OPENAI_API_KEY=[REDACTED]
GONKAGATE_API_KEY=[REDACTED]
```

## Basic Text Turn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ model:
provider: custom
base_url: https://api.gonkagate.com/v1
default: qwen/qwen3-235b-a22b-instruct-2507-fp8
api_key: ${GONKAGATE_API_KEY}
```

## Sanitized Env Shape

```dotenv
OPENAI_API_KEY=[REDACTED]
GONKAGATE_API_KEY=[REDACTED]
```

## Basic Text Turn
Expand Down
9 changes: 6 additions & 3 deletions docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ prompt. It does not accept a plain `--api-key` flag.
The canonical secret contract is:

- store the key only in the resolved Hermes `.env` file
- never write the key to `config.yaml`
- never write the raw key to `config.yaml`
- write only the non-secret `model.api_key = ${GONKAGATE_API_KEY}` reference
to `config.yaml`
- never print the raw key to stdout or stderr
- redact raw `gp-...` values and `Bearer` tokens in unexpected error paths

Expand All @@ -22,10 +24,11 @@ The helper writes only the minimum GonkaGate-managed surface:
- `model.provider`
- `model.base_url`
- `model.default`
- `OPENAI_API_KEY`
- `model.api_key = ${GONKAGATE_API_KEY}`
- `GONKAGATE_API_KEY`

Conflict-only cleanup is limited to current model-owned surfaces:
`model.api_key`, `model.api`, and incompatible `model.api_mode`.
`model.api` and incompatible `model.api_mode`.

Write safety rules:

Expand Down
30 changes: 15 additions & 15 deletions docs/specs/hermes-agent-setup-prd/implementation-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ Hermes behavior and must stay explicit about that boundary.
## Task 5: Implement shared-key and base-URL conflict classification

**Description:** Encode the PRD finite matrix for shared `OPENAI_API_KEY`
takeover and the exact `OPENAI_BASE_URL` rules. The output of this task should
be typed conflict data that the review planner can render without guessing.
consumers and the exact `OPENAI_BASE_URL` rules. The output of this task should
be typed compatibility data that the review planner can render without
guessing.

**Acceptance criteria:**

Expand All @@ -248,7 +249,7 @@ be typed conflict data that the review planner can render without guessing.
- [ ] Typecheck passes: `npm run typecheck`
- [ ] Conflict-classification tests pass: `npm test`
- [ ] Manual check: sample fixtures produce the expected matched-surface list
for takeover and `OPENAI_BASE_URL` scenarios
for shared-key and `OPENAI_BASE_URL` scenarios

**Dependencies:** Task 4

Expand Down Expand Up @@ -444,13 +445,13 @@ limits.
**Acceptance criteria:**

- [ ] The planner writes or updates `model.provider`, `model.base_url`,
`model.default`, and canonical `model.api_mode` state without broad
config ownership.
`model.default`, `model.api_key = ${GONKAGATE_API_KEY}`, and canonical
`model.api_mode` state without broad config ownership.
- [ ] Missing `config.yaml` produces only the exact minimal bootstrap contract
from FR3 and does not materialize unrelated default sections.
- [ ] Existing unrelated config is preserved semantically, while conflicting
`model.api_key`, `model.api`, incompatible `model.api_mode`, and allowed
matching-entry scrub fields are handled according to FR6.
`model.api`, incompatible `model.api_mode`, and allowed matching-entry
scrub fields are handled according to FR6.

**Verification:**

Expand All @@ -475,17 +476,16 @@ limits.

**Description:** Plan the `.env` changes owned by the helper and render the
single pre-write review block required by the PRD. This task covers
`OPENAI_API_KEY`, file-backed `OPENAI_BASE_URL` cleanup, and the one-prompt
confirmation rule.
`GONKAGATE_API_KEY` while preserving unrelated `OPENAI_API_KEY` and
file-backed `OPENAI_BASE_URL` residue outside helper ownership.

**Acceptance criteria:**

- [ ] The `.env` planner writes `OPENAI_API_KEY=<key>`, keeps unrelated env
keys intact, and applies the PRD cleanup rules for file-backed
- [ ] The `.env` planner writes `GONKAGATE_API_KEY=<key>` and keeps unrelated
env keys intact, including existing `OPENAI_API_KEY` and
`OPENAI_BASE_URL`.
- [ ] The review renderer shows one consolidated block with planned writes,
cleanup actions, matched takeover surfaces, and any required confirmation.
- [ ] Declining the confirmation exits cleanly without touching any file.
cleanup actions, and blocking conflicts.

**Verification:**

Expand Down Expand Up @@ -603,7 +603,7 @@ behavior tests.
**Acceptance criteria:**

- [ ] The test matrix covers clean homes, missing config, malformed YAML,
shared-key takeover confirmation, inherited and file-backed
shared-key preservation, inherited and file-backed
`OPENAI_BASE_URL`, matching named-provider conflicts, auth-pool aborts,
backup/rollback paths, unsupported platforms, and explicit `--profile`.
- [ ] Fixtures cover default profile, sticky profile, custom `HERMES_HOME`,
Expand Down Expand Up @@ -848,7 +848,7 @@ This task is the final freeze gate before calling the PRD implemented.
| Risk | Impact | Mitigation |
| ------------------------------------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Hermes normalized-read behavior drifts after the pinned upstream release | High | Keep the compatibility adapter explicit, back it with fixtures from the pinned release, and require requalification before claiming compatibility with newer Hermes releases |
| Shared `OPENAI_API_KEY` takeover is misclassified | High | Encode the finite matrix directly from FR4, prefer safe aborts, and keep dedicated fixtures for every matched surface |
| Shared `OPENAI_API_KEY` preservation is misclassified | High | Encode the finite matrix directly from FR4 and keep dedicated fixtures for every matched surface |
| YAML merge or scrub logic damages unrelated user config | High | Limit the helper-managed surface, preserve unrelated semantics in tests, and keep backup plus rollback behavior mandatory |
| Live catalog and allowlist drift to zero launchable models | Medium | Load allowlist from checked-in qualification artifacts and abort cleanly on empty intersection before any write |
| Public docs, package text, and skills drift away from shipped behavior | Medium | Delay the doc flip until runtime completion, keep contract tests strict, and update mirrored skills in the same phase |
Expand Down
Loading
Loading