from __future__ import annotations

from typing import Any


DXCLI_VERSION = "0.6.28"
DXCLI_RELEASED_AT = "2026-05-15T02:52:59Z"

DEVELOPER_UPDATE_LOG: tuple[dict[str, Any], ...] = (
    {
        "timestamp": DXCLI_RELEASED_AT,
        "version": DXCLI_VERSION,
        "title": "direct dx command wrappers and model selectors",
        "summary": "Added direct dxs/dxsa/dxsd/dxsda/dxa/dxaa entry points and numeric model selectors for managed Codex sessions.",
        "changes": [
            "Installers now create dxs, dxsa, dxsd, dxsda, dxa, and dxaa wrappers alongside dx.",
            "Managed Codex session creation expands trailing selectors like 3, 4, 5, 44, and 54 into codex -m and reasoning-effort arguments.",
            "Remote install-release now refreshes the new command links when clients receive an updated dxcli release.",
        ],
    },
    {
        "timestamp": "2026-05-14T09:35:00Z",
        "version": "0.6.27",
        "title": "portable archive colocated with source",
        "summary": "Moved the portable release archive output into dxcli-portable so the upload pair lives in one directory.",
        "changes": [
            "build_portable_bundle.sh now writes dxcli-portable-<version>.tar.gz and dxcli-portable-latest.tar.gz inside dxcli-portable/.",
            "The archive builder excludes existing tar.gz files so release bundles do not contain older bundles or themselves.",
            "Updated deployment docs to upload the installer script and archive from dxcli-portable/ directly.",
        ],
    },
    {
        "timestamp": "2026-05-14T09:05:00Z",
        "version": "0.6.26",
        "title": "portable archive installer",
        "summary": "Packaged dxcli-portable for two-file deployment with a tar.gz archive and a standalone installer script.",
        "changes": [
            "Added a portable bundle builder that creates dist/dxcli-portable-<version>.tar.gz.",
            "Added a standalone installer that extracts the archive, overwrites the install directory, and runs portable setup.",
            "Documented the two-file upload flow for installing dxcli-portable without copying the whole source directory.",
        ],
    },
    {
        "timestamp": "2026-05-14T08:20:00Z",
        "version": "0.6.25",
        "title": "portable client and release symlink alignment",
        "summary": "Added the portable Telegram-only client variant and aligned release installation wrappers with symlink-based version switching.",
        "changes": [
            "Added dxcli-portable as a no-controller client that sends Codex Stop completion notices directly to Telegram.",
            "Kept the shared session, tmux, terminal filter, and metadata version aligned across dxcli and dxcli-portable.",
            "install-release now refreshes dx and dx-remote as symlinks into the current release, matching the release switching contract.",
        ],
    },
    {
        "timestamp": "2026-05-14T07:36:00Z",
        "version": "0.6.24",
        "title": "native mouse selection restore",
        "summary": "Disabled tmux mouse capture by default so terminal text selection can be copied normally.",
        "changes": [
            "Managed tmux sessions now set mouse off by default and no longer bind MouseDrag1Pane to copy-mode.",
            "Wheel scrolling remains handled by the dxcli terminal input filter for managed Codex and shell processes.",
            "Set DXCLI_TMUX_MOUSE=1 before starting a session to opt back into tmux-managed mouse selection.",
        ],
    },
    {
        "timestamp": "2026-05-14T07:36:00Z",
        "version": "0.6.23",
        "title": "Codex hooks feature rename",
        "summary": "Switched managed Codex sessions from the deprecated codex_hooks feature flag to the current hooks flag.",
        "changes": [
            "Managed sessions now start Codex with --enable hooks instead of --enable codex_hooks.",
            "Hook installation now writes [features].hooks = true into ~/.codex/config.toml and removes the deprecated key.",
            "The installer also deduplicates old dxcli Stop hook entries while preserving the active /root/ls/dxcli hook.",
        ],
    },
    {
        "timestamp": "2026-05-14T07:36:00Z",
        "version": "0.6.22",
        "title": "hook completion log forwarding",
        "summary": "Codex Stop hook events now include a bounded transcript excerpt so the controller can notify Telegram without automatic model actions.",
        "changes": [
            "Stop hook reads the transcript tail when available and includes completion_log in the webhook event.",
            "The existing last_assistant_message remains available as a compact fallback.",
            "This supports a human-in-the-loop flow where Telegram replies decide any follow-up input.",
        ],
    },
    {
        "timestamp": "2026-05-14T05:20:00Z",
        "version": "0.6.21",
        "title": "pure copy-mode scroll-down",
        "summary": "Removed automatic copy-mode cancel from down-scroll bindings so downward wheel movement is not interrupted.",
        "changes": [
            "copy-mode and copy-mode-vi Down/WheelDown/PageDown variants now run only scroll-down.",
            "Removed the scroll_position cancel check from copy-mode down-scroll bindings.",
            "This prioritizes reliable downward movement before reintroducing any automatic exit behavior.",
        ],
    },
    {
        "timestamp": "2026-05-14T05:05:00Z",
        "version": "0.6.20",
        "title": "copy-mode down-wheel variants",
        "summary": "Expanded copy-mode-only scroll bindings so FinalShell down-wheel variants continue scrolling down after scrollback mode is active.",
        "changes": [
            "copy-mode and copy-mode-vi now bind Shift/Ctrl/Alt Down plus PageDown/NPage to scroll-down.",
            "Matching upward variants are bound only inside copy-mode for consistency.",
            "The root key table still does not bind cursor/page keys, preserving normal Codex and shell navigation outside scrollback.",
        ],
    },
    {
        "timestamp": "2026-05-14T04:50:00Z",
        "version": "0.6.19",
        "title": "copy-mode cursor wheel continuation",
        "summary": "Allowed FinalShell wheel input to continue scrolling after the first wheel event enters tmux copy-mode.",
        "changes": [
            "Root key table still does not bind Up/Down, preserving Codex selection and normal shell cursor behavior.",
            "copy-mode and copy-mode-vi now bind Up/Down to scroll actions because FinalShell cursor-wheel input is consumed by tmux once copy-mode is active.",
            "This prevents the scrollback view from appearing stuck after the first upward wheel event.",
        ],
    },
    {
        "timestamp": "2026-05-14T04:35:00Z",
        "version": "0.6.18",
        "title": "smoother persistent scrollback",
        "summary": "Improved FinalShell scroll smoothness and stopped upward scrollback from automatically resetting to the live bottom.",
        "changes": [
            "Increased the tmux wheel scroll step from 3 to 5 lines.",
            "Widened the FinalShell cursor-wheel coalescing window so wheel bursts are handled more continuously.",
            "Removed idle copy-mode auto-exit after upward scrolling; copy-mode now exits only when scrolling down to the live bottom.",
        ],
    },
    {
        "timestamp": "2026-05-14T04:20:00Z",
        "version": "0.6.17",
        "title": "FinalShell wheel heuristic",
        "summary": "Replaced unconditional cursor-key interception with a short coalescing heuristic so keyboard navigation still works while rapid FinalShell wheel bursts scroll tmux.",
        "changes": [
            "A single ESC[A or ESC[B is delayed briefly and then passed through to Codex or the shell.",
            "Rapid repeated ESC[A/ESC[B bursts are treated as FinalShell mouse wheel input and converted to tmux scrolling.",
            "After wheel scrolling, tmux copy-mode exits automatically after a short idle delay to avoid requiring Esc.",
        ],
    },
    {
        "timestamp": "2026-05-14T04:05:00Z",
        "version": "0.6.16",
        "title": "FinalShell cursor-wheel compatibility",
        "summary": "Enabled a targeted FinalShell compatibility filter for clients that send mouse wheel movement as plain cursor Up/Down sequences.",
        "changes": [
            "The PTY filter now converts plain ESC[A and ESC[B into tmux scroll actions by default.",
            "Application cursor sequences, modified cursor keys, PageUp/PageDown, and normal tmux wheel events remain separate.",
            "Set DXCLI_FINALSHELL_CURSOR_WHEEL_FILTER=0 before starting a managed session to disable this compatibility filter.",
        ],
    },
    {
        "timestamp": "2026-05-14T03:50:00Z",
        "version": "0.6.15",
        "title": "mouse-wheel-only interception",
        "summary": "Restricted dx managed scroll handling to actual mouse wheel events only, leaving all cursor and page keys to Codex or the shell.",
        "changes": [
            "Removed tmux bindings for Up/Down, modified cursor keys, PageUp, and PageDown from the managed profile.",
            "The PTY input filter now intercepts only SGR mouse wheel sequences and passes all keyboard cursor/page sequences through.",
            "This applies consistently to dx s, dx sd, local attach, and global attach sessions after the profile is reapplied.",
        ],
    },
    {
        "timestamp": "2026-05-14T03:35:00Z",
        "version": "0.6.14",
        "title": "codex selection cursor passthrough",
        "summary": "Narrowed the FinalShell input filter so Codex selection UIs can receive normal Up/Down cursor keys and refresh immediately.",
        "changes": [
            "Codex managed sessions no longer intercept plain Up/Down cursor sequences by default.",
            "The filter still intercepts modified cursor keys, PageUp/PageDown, and SGR mouse wheel sequences for scroll containment.",
            "Managed shell sessions keep plain cursor-key interception by default to prevent FinalShell wheel input from recalling shell history.",
        ],
    },
    {
        "timestamp": "2026-05-14T03:20:00Z",
        "version": "0.6.13",
        "title": "FinalShell input filter",
        "summary": "Added a managed-session PTY input filter for FinalShell-style wheel events that bypass tmux key bindings and reach Codex or the shell as cursor keys.",
        "changes": [
            "Managed Codex and shell sessions now launch through a small PTY relay before starting the real command.",
            "The relay intercepts Up/Down, modified Up/Down, PageUp/PageDown, and SGR wheel mouse sequences before they reach the child process.",
            "Intercepted upward input enters tmux copy-mode and scrolls up; downward input scrolls down and exits copy-mode at the live bottom.",
        ],
    },
    {
        "timestamp": "2026-05-14T03:05:00Z",
        "version": "0.6.12",
        "title": "expanded wheel translation capture",
        "summary": "Expanded tmux fallback bindings so terminal-translated wheel input is captured as page scrolling across more SSH clients.",
        "changes": [
            "Managed tmux sessions now bind Shift/Ctrl/Alt Up/Down plus PageUp/PageDown fallback keys to scroll actions.",
            "Enabled tmux xterm-keys and extended-keys so modified cursor sequences are decoded before they can reach Codex or the shell.",
            "Root, copy-mode, and copy-mode-vi tables now share the same scroll key strategy, reducing future drift.",
        ],
    },
    {
        "timestamp": "2026-05-14T02:50:00Z",
        "version": "0.6.11",
        "title": "wheel-as-arrow fallback",
        "summary": "Added Up/Down key fallback bindings for terminals that translate mouse wheel input into arrow keys before tmux sees it.",
        "changes": [
            "Root Up now enters copy-mode and scrolls up, matching WheelUpPane behavior.",
            "Root Down and copy-mode Down now scroll down, with automatic copy-mode exit at the live bottom.",
            "This prevents terminal-translated wheel input from reaching Codex or the shell as command-history navigation.",
        ],
    },
    {
        "timestamp": "2026-05-14T02:35:00Z",
        "version": "0.6.10",
        "title": "wheel scroll containment hardening",
        "summary": "Hardened mouse-wheel behavior so scrolling is used for tmux page viewing instead of command-history navigation.",
        "changes": [
            "dx attach sends the xterm sequence to disable outer alternate-scroll key translation before entering tmux.",
            "copy-mode wheel-down now exits copy-mode automatically when scrolled back to the live bottom.",
            "tmux terminal-overrides are now applied idempotently instead of accumulating duplicate entries on every attach.",
        ],
    },
    {
        "timestamp": "2026-05-14T02:20:00Z",
        "version": "0.6.9",
        "title": "new managed codex sessions are independent by default",
        "summary": "Reverted the implicit `resume --last` default so `dx s <id>` creates an independent Codex session unless resume args are explicitly provided.",
        "changes": [
            "dx s <local_id> and dx sa <global_id> no longer default to `resume --last`.",
            "Use `dx s <local_id> resume --last` when the desired behavior is to reopen the latest Codex conversation.",
            "This prevents multiple managed sessions from all attaching to the same Codex history by default.",
        ],
    },
    {
        "timestamp": "2026-05-14T02:05:00Z",
        "version": "0.6.8",
        "title": "copy-mode attach cleanup and mouse capture restore",
        "summary": "Attach now exits stale tmux copy-mode before entering the session, and managed sessions keep tmux mouse capture enabled.",
        "changes": [
            "dx a and dx aa cancel copy-mode before attach so the UI does not open in scrollback history.",
            "Managed tmux sessions now keep session-level mouse on so wheel events are captured by tmux instead of being translated by the outer terminal.",
            "Attach now passes the stored launch mode into the managed tmux profile.",
        ],
    },
    {
        "timestamp": "2026-05-14T01:50:00Z",
        "version": "0.6.7",
        "title": "remove alternate-scroll escape residue",
        "summary": "Removed the remaining session-start terminal escape that disabled xterm alternate-scroll behavior inside managed Codex runs.",
        "changes": [
            "Managed session startup no longer writes CSI ? 1007 l to stdout.",
            "This brings dx-managed Codex closer to a directly launched Codex terminal environment.",
            "Added a regression test to ensure managed startup does not write terminal control sequences.",
        ],
    },
    {
        "timestamp": "2026-05-14T01:35:00Z",
        "version": "0.6.6",
        "title": "managed resume default restored",
        "summary": "Managed codex sessions now default to `resume --last` again when no explicit codex args are provided.",
        "changes": [
            "dx s and dx sa now reopen the latest Codex conversation by default instead of entering a fresh picker state.",
            "This removes the need to press Ctrl+C once just to get back to the prior session flow.",
            "Explicit codex args still override the default behavior.",
        ],
    },
    {
        "timestamp": "2026-05-14T01:20:00Z",
        "version": "0.6.5",
        "title": "native codex scroll strategy",
        "summary": "Shifted managed codex sessions closer to native terminal behavior by restoring alternate screen and turning off tmux mouse at the session level for codex launches.",
        "changes": [
            "Managed codex sessions no longer default to --no-alt-screen.",
            "tmux session-level mouse is now disabled for codex launches so wheel handling stays with the inner Codex TUI.",
            "Shell launches still keep tmux mouse enabled.",
        ],
    },
    {
        "timestamp": "2026-05-14T01:05:00Z",
        "version": "0.6.4",
        "title": "pane display regression rollback",
        "summary": "Removed the direct escape-sequence injection into managed panes because it could disturb the Codex TUI rendering on first entry.",
        "changes": [
            "Stopped sending the alternate-scroll disable sequence directly into the tmux pane.",
            "Kept the client-side attach terminal handling and the launch ordering fix from 0.6.3.",
            "Restored normal first-entry Codex rendering while keeping the newer launch pipeline intact.",
        ],
    },
    {
        "timestamp": "2026-05-14T00:45:00Z",
        "version": "0.6.3",
        "title": "attached launch ordering fix",
        "summary": "Managed sessions created via dx s/dx sa now start detached, receive the tmux profile first, and only then attach the client terminal.",
        "changes": [
            "dx s and dx sa no longer enter tmux before the managed profile is applied.",
            "The attach-time terminal compatibility fixes now also apply to the immediate-create path, not only later dx a re-attachments.",
            "Remote detached creation behavior stays unchanged while local interactive creation now uses the same attach pipeline consistently.",
        ],
    },
    {
        "timestamp": "2026-05-14T00:30:00Z",
        "version": "0.6.2",
        "title": "managed codex no-alt-screen default restored",
        "summary": "Restored --no-alt-screen as the default for managed codex sessions so wheel events are not reinterpreted by the inner application.",
        "changes": [
            "Managed codex sessions now add --no-alt-screen by default again.",
            "DXCLI_MANAGED_NO_ALT_SCREEN=0 can still be used to opt back into alternate screen for debugging.",
            "Release metadata and developer log were bumped to track the behavior change separately from tmux-only fixes.",
        ],
    },
    {
        "timestamp": "2026-05-14T00:00:00Z",
        "version": "0.6.1",
        "title": "scroll wheel compatibility hardening",
        "summary": "Disabled alternate scroll at both client attach and managed pane startup, and normalized tmux attach to UTF-8 mode.",
        "changes": [
            "dx attach now disables terminal alternate scroll before entering tmux to stop wheel events from becoming shell history navigation.",
            "Managed panes now also send the alternate-scroll disable sequence and force tmux attach with -u to reduce SSH rendering glitches.",
            "tmux pane defaults now explicitly disable passthrough and keep pane/window behavior aligned for managed sessions.",
        ],
    },
    {
        "timestamp": "2026-05-13T00:00:00Z",
        "version": "0.6.0",
        "title": "tmux scroll and shell-mode refresh",
        "summary": "Added shell sessions, stronger tmux scrollback defaults, and SSH-friendly terminal tuning.",
        "changes": [
            "dx sd <local_id> and dx sda <global_id> now start a managed shell instead of auto-starting codex.",
            "Managed tmux sessions now default to wheel scrolling in copy mode and keep a much larger history buffer.",
            "Managed runtime metadata now includes version and developer update entries for remote inspection and release tracking.",
        ],
    },
)


def current_release_metadata() -> dict[str, Any]:
    latest_update = dict(DEVELOPER_UPDATE_LOG[0]) if DEVELOPER_UPDATE_LOG else None
    return {
        "version": DXCLI_VERSION,
        "released_at": DXCLI_RELEASED_AT,
        "latest_update": latest_update,
        "developer_updates": [dict(item) for item in DEVELOPER_UPDATE_LOG],
    }
