import { type ActivityEvent, type Attachment } from './feed/activity.js';
import { type PidSessionEntry } from './session/pid-registry.js';
/** Soft cap so a runaway agent can't flood the activity lane with essays. */
export declare const STATUS_POST_MAX_CHARS = 500;
/** Title is a phone subject line - about four or five words, not a paragraph. */
export declare const STATUS_TITLE_MAX_CHARS = 60;
export interface FeedPostInput {
    /**
     * Short subject (required for new posts). ~4–5 words. Phone broadcasts put
     * this on the first line so a scan names the topic before the body.
     */
    title: string;
    /** Body text (required). Domain-agnostic free text — what happened / the ask. */
    text: string;
    /** Override session id (escape hatch for scripts/tests). Prefer auto-resolve. */
    sessionId?: string;
    /** Generic artifacts to attach: local paths (copied for durability) or URLs. */
    attach?: string[];
    /**
     * The agent is STUCK, not merely reporting. Writes `status.blocked` instead of
     * `status.posted`, and the caller pairs it with an OpenBlock so the ask stays
     * answerable until someone resolves it.
     *
     * This is a state, not a volume: a blocked post is always broadcast at
     * `important`, so an agent never has to decide the level as well. One thing to
     * say is what makes the habit stick.
     */
    blocked?: boolean;
    /** Override activity root (tests). */
    activityRoot?: string;
    /**
     * Override the attachments store root (tests). Local files are copied under
     * `<attachmentsRoot>/<sessionId>/<updateId>/`. Defaults to
     * `~/.agents/.history/attachments`.
     */
    attachmentsRoot?: string;
    /** Override env for identity resolution (tests). */
    env?: NodeJS.ProcessEnv;
    /** Override cwd stamp (defaults to process.cwd() / env). */
    cwd?: string;
    /** Fixed timestamp (tests). */
    ts?: string;
    /**
     * Starting pid for registry ancestor walk (defaults to process.ppid so the
     * walk begins at the parent of this CLI process — usually the agent/shell).
     * Tests inject a fake pid here.
     */
    startPid?: number;
    /** Override parent-pid lookup (tests). */
    getParentPid?: (pid: number) => number | undefined;
    /** Override registry read (tests). */
    readEntry?: (pid: number) => PidSessionEntry | undefined;
    /** Override full registry list for launchId match (tests). */
    listEntries?: () => PidSessionEntry[];
}
export interface FeedPostResult {
    event: ActivityEvent;
}
export interface PostIdentity {
    sessionId: string;
    mailboxId: string;
    host: string;
    runtime: string;
    agent?: string;
    cwd?: string;
    pid?: number;
    launchId?: string;
    terminalId?: string;
    tmuxPane?: string;
}
/**
 * Resolve who is posting. Order:
 *  1. Explicit --session flag
 *  2. Env: AGENT_SESSION_ID / AGENTS_SESSION_ID / basename(AGENTS_MAILBOX_DIR)
 *  3. Env AGENT_LAUNCH_ID → match in pid registry or activity index
 *  4. Walk parent PIDs from startPid (default process.ppid) through by-pid registry
 */
export declare function resolvePostIdentity(input: Pick<FeedPostInput, 'sessionId' | 'env' | 'cwd' | 'activityRoot' | 'startPid' | 'getParentPid' | 'readEntry' | 'listEntries'>): PostIdentity | undefined;
/** Walk up to 16 ancestors looking for a by-pid registry entry with a session. */
export declare function walkPidRegistry(startPid: number, getParent: (pid: number) => number | undefined, readEntry: (pid: number) => PidSessionEntry | undefined): PidSessionEntry | undefined;
/** Best-effort parent pid of `pid` (Linux /proc, else `ps`). */
export declare function parentPidOf(pid: number): number | undefined;
/**
 * Turn one `--attach` token into an {@link Attachment}. Remote URLs become
 * `link` (or a media kind when the extension is unambiguous). Local files are
 * classified by extension and, when `copyRoot` is set, copied under
 * `<copyRoot>/<sessionId>/<updateId>/<basename>` so the link survives a worktree
 * delete — the stored `href` then points at the durable copy. A missing local
 * file is dropped (fail-open) rather than throwing.
 */
export declare function buildAttachment(token: string, ctx: {
    copyRoot?: string;
    sessionId: string;
    updateId: string;
}): Attachment | undefined;
/** Classify + store every `--attach` token; empty/failed tokens are dropped. */
export declare function buildAttachments(tokens: string[] | undefined, ctx: {
    copyRoot?: string;
    sessionId: string;
    updateId: string;
}): Attachment[];
/**
 * Collapse whitespace and strip em/en dashes (house rule: no em-dashes in
 * agent-authored outbound copy — phones and plain text render them poorly).
 */
export declare function scrubDashes(text: string): string;
export declare function normalizeStatusText(text: string): string;
/** Normalize a short subject line for a post. */
export declare function normalizeStatusTitle(title: string): string;
/**
 * Append a `status.posted` milestone for the calling agent.
 * Throws if title/text is empty or session identity cannot be resolved.
 */
export declare function postFeedStatus(input: FeedPostInput): FeedPostResult;
