feat(telegram): send Claude Code login links to the bot owner

This commit is contained in:
EugeneTes
2026-09-25 17:45:11 +00:00
parent 1aa9197d9c
commit df0a518b97
7 changed files with 192 additions and 3 deletions

View File

@@ -24,7 +24,8 @@ o.DefaultModel = "claude-code/sonnet"; // or opus, haiku, fable, or the pin
```
Run `/claude-code-doctor` in a session to check the installation, auth, required CLI flags and the bridge
handshake. It costs no quota.
handshake. It costs no quota. If it reports "not logged in", run `/claude-code-login` (see below) or `claude
auth login` on the host.
## How it works
@@ -54,6 +55,36 @@ conversation is replayed each time.
`apiKeySource == "none"` (proof of subscription auth) and a connected `volcanic` MCP server. Anything else
fails closed.
## Session expiry and re-login
A `claude` subscription session can expire mid-use (a 401, or the CLI's own "Please run /login" / "Invalid API
key" wording). The provider detects this from the stream and, given somewhere to send the owner a link, logs
back in without failing the request outright:
1. The failing request pauses instead of erroring, as long as nothing has reached the caller yet (no partial
reply, no tool call).
2. If a `ClaudeCodeProviderOptions.LoginUi` is configured, its `IUserInterface` gets a notification with the
`claude auth login --claudeai` link, then an input prompt ("Paste the Claude login code") for the code shown
on the page.
3. `ClaudeLoginCoordinator` keeps this to one flow at a time: concurrent expired requests all wait on the same
login instead of racing the CLI.
4. A wrong code gets a fresh link, up to 3 attempts; the owner has 10 minutes to answer each prompt
(`ClaudeLoginOptions.CodeTimeout`), and resolving where the owner is has 30 seconds
(`ClaudeLoginOptions.OwnerTimeout`) before they count as unreachable.
5. On success the paused request replays exactly once; a failure there (including expiring again immediately)
is published as-is, so there is no retry loop.
6. **`LoginUi` is null** (the default, e.g. headless hosts): no login flow runs. The request fails with
`[auth] Claude Code session expired; run "claude auth login" on the host (or /claude-code-login from a chat
UI)`.
Run `/claude-code-login` in any session with a UI to sign in (or switch accounts) through that session's own
dialog, with no owner redirect — useful even before the session has expired. Without a UI it explains that it
needs one instead of failing silently.
`ClaudeCodeProviderOptions` carries the pieces a host wires up: `LoginUi` (where the link goes),
`Coordinator` (defaults to the process-wide `ClaudeLoginCoordinator.Shared`), and `LoginOptions` (the timeouts
and attempt budget above). The Telegram host points `LoginUi` at the first `AllowedUserIds` entry's private chat.
## Limitations (inherited from the design)
- Full-history replay costs more context than the Messages API and cannot replay thinking signatures.