Skip to content

The settings page has no GitHub-account login for aitokenpool, so a user hand-types three fields that fail silently #2774

Closed

Description

@argszero

What is missing

The GUI settings page (Model services tab, emrg/gui/renderer/src/components/SettingsPanel.tsx) offers exactly three fields for a model endpoint: API key, base URL and default model. Nothing else. A user who wants to use aitokenpool must first open its website, register an account, copy an API key, and then hand-fill all three fields.

aitokenpool already supports registering and signing in with a GitHub identity — an account can be opened without an email address — through a standard OAuth device flow. EMRG exposes no entry point for it, so that capability is unreachable from inside the only non-terminal surface this project has.

The failure mode is the reason this matters more than convenience: any one of the three fields being wrong (trailing /v1, a stale key, a model name the endpoint does not serve) presents as "the model does not answer". Diagnosing that costs far more than configuring it.

What is expected

One action in the settings page: click a button, authorize in the system browser, come back, and the API key, service address and default model are already configured and ready to use.

Requirements

  1. The Model services tab gains an aitokenpool account block above the existing model fields: when not signed in, one line of explanation plus a Sign in with GitHub button.
  2. The button opens a dialog showing a large one-time code (copyable), an Open browser action and a waiting for authorization state; the authorization URL the server returned is opened in the system browser.
  3. Poll at the interval the server returns. A 429 must be honoured silently by switching to the new interval — the user sees nothing.
  4. On success, the new key is first exercised against the protected GET /api/models; a non-200 response means nothing is written and an error is shown.
  5. Only after that probe passes is [llm] written: base_url = <service address>/v1, api_key, and model = deepseek-flash; context_window is taken from the server's model list.
  6. If [[llm.models]] already carries an entry named deepseek-flash, only its context_window is updated — no second entry is appended.
  7. Every other key in [llm] — including hand-added ones such as base_url_1 or api_key3 — and every other section is preserved verbatim. Not one byte of them changes.
  8. When api_key is already non-empty, the write is preceded by a confirmation that this replaces the key and address currently in use; cancel means zero writes.
  9. On success the dialog closes, the three fields are filled into the existing form and saved, and the confirmation names the GitHub user and the model that is now ready.
  10. The service address is switchable: default https://aitokenpool.args.fun, alternatively https://atp-dev.shenbiai.net. Changing the address does not trigger a login.
  11. Each of the four failures says what to do next — service not enabled (503), code expired (410), user denied (403), service unreachable. A bare "failed" is not an answer.
  12. Not to be built: signed-in state detection and a disconnect button. There is no reliable way to derive an identity from a key, and a fabricated state indicator is worse than none.
  13. An already-connected TUI session needs no login entry, but a config change must show the new model name immediately — never a restart.

Server contract

Already deployed; the field names and status codes below are fixed and must not be changed by this work.

  • POST /api/auth/github/device/code → 200 {device_code, user_code, verification_uri, expires_in, interval}; when the deployment has GitHub login switched off, 503 github_login_not_enabled.
  • POST /api/auth/github/device/token with {device_code} → 200 {api_key, user_id, login}; intermediate states carry 202 authorization_pending, 429 slow_down, 410 expired_token, 403 access_denied.

Acceptance

  1. Renderer test: click produces a code → polling succeeds → the filled-in field values are correct; each of the four failure states matches its own message.
  2. On cancelling the overwrite confirmation the write function is called zero times (assert the call count, not that the file's contents are unchanged).
  3. Write test: a [llm] preseeded with custom keys such as base_url_1 and api_key3 keeps them verbatim after the write.
  4. Write test: an existing [[llm.models]] entry of the same name is not duplicated — only its context_window changes.
  5. The whole flow runs against a fake upstream and never leaves the machine; the positive control is: a 200 from the fake upstream really writes, a 202 really writes nothing.
  6. Mutation check: turning "confirm before overwrite" into a direct overwrite must redden a test; rewriting the whole [llm] section instead of preserving keys must redden a test.
  7. Daemon side: a change to [llm] model takes effect within 2 seconds and is broadcast to connected clients.
  8. Green on all three CI platforms (ubuntu / windows / macos).

Where the work lives

  • emrg/gui/renderer/src/components/ — the settings section and the login dialog (the existing GithubDeviceDialog.tsx is the shape to follow).
  • emrg/gui/main.js + emrg/gui/preload.js — the renderer has no network access (sandboxed, contextIsolation), so the HTTP calls and the config write belong to the main process, reached through a whitelisted IPC channel.
  • ~/.emrg/config.toml — [llm] and [[llm.models]]; the existing emrg:saveSettings handler already merges rather than replaces.

Activity

  1. argszero commented on Nov 9, 2026

    @argszero
    OwnerAuthor

    Handled by #2775

  2. argszero commented on Nov 9, 2026

    @argszero
    OwnerAuthor

    On acceptance item 8: this repository's CI runs two legs, not three. .github/workflows/test.yml has test (ubuntu) and test-windows; macOS is exercised only by the tag-triggered build-release.yml, which no pull request can run. So item 8 is read as met when both PR legs are green, which they are on head 59ad6b47 (run 42642395006: test 2m54s, test-windows 5m33s) — the third platform is covered by the release build, not by CI on a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions