/** * Login expiry rules — per-harness patterns that mean "this agent's harness * login has expired and a human has to sign in again". * * Used by the OAuth re-login monitor on agent terminal output (live PTY * chunks and the periodic screen sweep). A match is handed to the harness * re-login coordinator (harness-relogin.service.ts), which runs one broker * login per harness and asks the owner over Slack. * * Output is normalized with {@link normalizeTerminalOutput} first, and every * pattern is matched against the normalized text and its spaceless copy, * because Claude Code places words with cursor moves instead of spaces. * Patterns therefore use `\s*` between words. * * Wording sources: * - Claude Code 2.1.282, from the binary (`strings`, 2026-09-25): * `Login expired · Please run /login`, `OAuth token revoked · Please run * /login`, `Not logged in · Please run /login`, `API Error: 401 Invalid * API key · Please run /login`, `Session expired. Please run /login to sign * in again.`, and the API's own `OAuth token has expired` / * `OAuth token has been revoked` inside an `authentication_error`. * Deliberately NOT matched: the warning `Your login expires in 3 days · * run /login to renew` (the login still works). * - Codex (codex-rs auth refresh errors and the Responses API 401): `Your * access token could not be refreshed because your refresh token has * expired`, `Provided authentication token is expired`, * `"code":"token_expired"`, `unexpected status 401 Unauthorized`. * * UI messages require Claude's `·` separator, so an agent that merely reads * source code mentioning "please run /login" does not trip them; API errors * require the `authentication_error` / `401` context in the same text. * * @module services/harness/login-expiry-rules */ import type { HarnessId } from './harness.types.js'; /** One expiry rule: every pattern must match (AND). */ export interface LoginExpiryRule { /** Stable id, used in logs (never contains output) */ id: string; harnessId: HarnessId; /** All must match the normalized text or its spaceless copy */ all: readonly RegExp[]; } /** What {@link detectLoginExpiry} found. */ export interface LoginExpiryMatch { harnessId: HarnessId; /** Id of the rule that matched */ ruleId: string; } /** Claude Code expiry rules. */ export declare const CLAUDE_EXPIRY_RULES: readonly LoginExpiryRule[]; /** Codex expiry rules. */ export declare const CODEX_EXPIRY_RULES: readonly LoginExpiryRule[]; /** * Expiry rules for a harness (or for every harness when the runtime is unknown). * * @param harnessId - Harness / runtime id, or null * @returns Rules to try */ export declare function getLoginExpiryRules(harnessId: string | null): readonly LoginExpiryRule[]; /** * Find an expired-login message in agent terminal output. * * @param output - Raw PTY output (escape sequences allowed) or captured screen text * @param harnessId - The agent's runtime (a harness id), or null to try every harness * @returns The harness whose login expired and the rule that matched, or null * * @example * ```ts * detectLoginExpiry(' ⎿ Login expired · Please run /login', 'claude-code'); * // { harnessId: 'claude-code', ruleId: 'claude.login_expired' } * ``` */ export declare function detectLoginExpiry(output: string, harnessId: string | null): LoginExpiryMatch | null; //# sourceMappingURL=login-expiry-rules.d.ts.map