/** * Owner login requests — recognising "log harness X in" in plain words. * * Two consumers: * - {@link parseOwnerLoginRequest}: the Slack DM interceptor. An owner who * writes 「重新登录 claude」, 「换个账号登录 claude」 or "relogin codex" in the * orchestrator's DM gets the login flow directly, without the LLM. The * match is deliberately strict — the whole message must be the request — * so a sentence that merely mentions a login still goes to the orc. * - {@link isOwnerLoginRequestEvidence}: the orchestrator's `harness-login` * skill. The orc may start a login only when a real owner message asked for * one; this is the evidence check over the owner's recent messages. * * `login claude@work` / `login claude account work` / 「登录 claude 账号 work」 * asks for one of the owner's OTHER Claude Code accounts (issue #942, * claude-accounts.ts); the request then carries `account`. The bare form * `login claude work` counts only for an account that already exists * ("login claude please" is not an account). * * Incident 2026-09-26: the orc ran `claude setup-token` in its one-shot bash * tool (the process died with the call, every pasted code went stale) and * then claimed several times that it had sent a new link. The broker-backed * flow started from here keeps the login alive in its own PTY. * * @module services/harness/owner-login-request */ import type { HarnessId } from './harness.types.js'; /** A recognised owner login request. */ export type OwnerLoginRequest = /** * A known harness (it may still have no broker login — Antigravity, Gemini). * `account`: one of the owner's other Claude Code accounts. */ { kind: 'harness'; harnessId: HarnessId; switchAccount: boolean; account?: string; } /** A login request without a harness Crewly knows; `name` is what was written, or null. */ | { kind: 'unknown'; name: string | null; switchAccount: boolean; }; /** Options of {@link parseOwnerLoginRequest}. */ export interface ParseOwnerLoginOptions { /** The owner's existing other Claude Code accounts (lets "login claude work" name one) */ knownClaudeAccounts?: readonly string[]; } /** * Normalise a DM for matching: drop Slack mention/link markup, collapse * whitespace, lower-case, trim. * * @param text - Raw message text * @returns Normalised text */ export declare function normaliseLoginText(text: string): string; /** * Resolve a harness name or alias as written by a person. * * @param name - e.g. "claude code", "Claude", "agy", "codex cli" * @returns The harness id, or null * * @example * ```ts * resolveHarnessName('claude code'); // 'claude-code' * ``` */ export declare function resolveHarnessName(name: string): HarnessId | null; /** * Recognise an owner's DM that asks Crewly to log a harness in (or switch * its account). The whole message must be the request; anything longer or * different returns null and is handled by the orchestrator as usual. * * @param text - Owner DM text * @param options - The owner's existing other Claude Code accounts * @returns The request, or null when the message is not a login request * * @example * ```ts * parseOwnerLoginRequest('换个账号登录 claude'); * // { kind: 'harness', harnessId: 'claude-code', switchAccount: true } * parseOwnerLoginRequest('重新登录'); * // { kind: 'unknown', name: null, switchAccount: false } * ``` */ export declare function parseOwnerLoginRequest(text: string, options?: ParseOwnerLoginOptions): OwnerLoginRequest | null; /** * Whether one owner message asks for a (re-)login of a harness. Mirrors the * install-skill approval check: the orchestrator's claim is not trusted, the * owner's own words are. * * Counts a message with a login verb that either names this harness or names * none (「不 我要重新登陆一个账号」 in a conversation about Claude). A message * naming only other harnesses, or a status question, does not count. * * @param message - Owner message text * @param harnessId - Harness the orchestrator wants to log in * @returns True when the message is evidence for that login */ export declare function isOwnerLoginRequestEvidence(message: string, harnessId: HarnessId): boolean; //# sourceMappingURL=owner-login-request.d.ts.map