
    j+                        d dl Z d dlZd dlZd dlZd dlZddlmZ ej                            d          Z	ej                            d          Z
ej                            d          Zej                            d          ZdZd	Zd
Z ej        dej                  Zg dZdZdee         defdZdeeef         dz  fdZdefdZdedz  fdZdefdZddZddeddfdZ ddZ!ddZ"ddZ#ddZ$ddZ%dS )     N   )consolez~/.claude/settings.jsonz~/.claude/tt-statusline.pyz~/.codex/config.tomlz~/.codex/tt-backup.jsonz1.1tokenTrackerpreviousStatusLinezstatus_line\s*=\s*\[.*?\])projectzfive-hour-limitzweekly-limitzcontext-remainingzmodel-with-reasoningu  #!/usr/bin/env python3
"""Claude Code statusLine — 状态栏显示 + 数据持久化到 tt-status.json"""
__version__ = "1.1"
import json, os, sys, tempfile
from datetime import datetime, timezone

STATUS_FILE = os.path.expanduser("~/.claude/tt-status.json")
BAR = ("█", "░", 8)
C = {
    "green": "\033[32m", "yellow": "\033[33m", "red": "\033[31m",
    "cyan": "\033[36m", "blue": "\033[34m", "magenta": "\033[35m",
    "peach": "\033[38;5;216m", "dim": "\033[2m", "reset": "\033[0m",
}


def color_by_pct(pct):
    return C["green"] if pct < 50 else C["yellow"] if pct < 80 else C["red"]


def fmt_tokens(n):
    if n >= 1_000_000: return f"{n/1_000_000:.1f}M"
    if n >= 1_000: return f"{n/1_000:.0f}k"
    return str(n)


def progress_bar(value):
    filled_char, empty_char, width = BAR
    if value is None:
        return empty_char * width + " n/a"
    pct = max(0.0, min(100.0, float(value)))
    filled = round(pct / 100 * width)
    return f"{color_by_pct(pct)}{filled_char * filled}{C['reset']}{empty_char * (width - filled)} {pct:.0f}%"


def save_data(data):
    data["_received_at"] = datetime.now(timezone.utc).isoformat()
    try:
        fd, tmp = tempfile.mkstemp(dir=os.path.dirname(STATUS_FILE), suffix=".tmp")
        with os.fdopen(fd, "w") as f:
            json.dump(data, f)
        os.replace(tmp, STATUS_FILE)
    except OSError:
        pass


def render(data):
    parts = []

    project = data.get("workspace", {}).get("project_dir", "")
    if project:
        parts.append(f"{C['cyan']}{os.path.basename(project)}{C['reset']}")

    rl = data.get("rate_limits", {})
    has_rl = False
    for key, label in [("five_hour", "5h"), ("seven_day", "7d")]:
        pct = rl.get(key, {}).get("used_percentage")
        if pct is not None:
            has_rl = True
            parts.append(f"{C['blue']}{label}:{C['reset']}{progress_bar(pct)}")

    if not has_rl:
        cost = data.get("cost", {})
        usd = cost.get("total_cost_usd")
        if usd is not None:
            parts.append(f"{C['blue']}Cost:{C['reset']}{C['peach']}${usd:.2f}{C['reset']}")

    ctx = data.get("context_window", {})
    if ctx.get("used_percentage") is not None:
        size = ctx.get("context_window_size", 0)
        pct = ctx["used_percentage"]
        cc = C["green"] if pct < 40 else C["yellow"] if pct < 60 else C["red"]
        parts.append(f"{cc}{fmt_tokens(size)} CTX: {pct:.0f}%{C['reset']}")

    total_in = ctx.get("total_input_tokens", 0)
    total_out = ctx.get("total_output_tokens", 0)
    cache = ctx.get("current_usage", {}).get("cache_read_input_tokens", 0)
    if total_in or total_out:
        parts.append(f"{C['peach']}Tokens: {fmt_tokens(total_in)}↑ {fmt_tokens(total_out)}↓ cached:{fmt_tokens(cache)}{C['reset']}")

    model_name = data.get("model", {}).get("display_name", "")
    if model_name:
        effort = data.get("effort", {}).get("level", "")
        if effort:
            model_name += f"{C['dim']}/{effort}{C['reset']}"
        parts.append(f"{C['magenta']}{model_name}{C['reset']}")

    if parts:
        print(" | ".join(parts))


def main():
    try:
        raw = sys.stdin.read()
        if not raw.strip():
            return
        data = json.loads(raw)
    except Exception:
        return
    save_data(data)
    render(data)


if __name__ == "__main__":
    main()
itemsreturnc                 L    d                     d | D                       }d| dS )Nz,
c              3   "   K   | ]
}d | dV  dS )z  ""N ).0items     ]C:\Users\Terasoftware\OneDrive\Desktop\faahhh\fyndo\fyndo\venv\Lib\site-packages\src/hooks.py	<genexpr>z$_status_line_toml.<locals>.<genexpr>   s*      66mDmmm666666    zstatus_line = [
z,
])join)r   bodys     r   _status_line_tomlr      s3    ::6666666D)t))))r   c                      	 t          t          dd          5 } |                                 }d d d            n# 1 swxY w Y   |t          j        |          fS # t
          t          j        f$ r Y d S w xY w)Nrutf-8encoding)openCODEX_CONFIGreadtomllibloadsOSErrorTOMLDecodeError)fcontents     r   _read_codex_configr$      s    ,g666 	!ffhhG	 	 	 	 	 	 	 	 	 	 	 	 	 	 	g....W,-   tts.   A :A >A >A A54A5c                     t           j                            t           j                            t                              } t           j                            t                    }| s|sdS | r	 t          t          dd          5 }t          j	        |          }d d d            n# 1 swxY w Y   |
                    d          }t          |t                    rd|
                    d          pdvrdS n# t          t          j        f$ r Y dS w xY w|rKt                      }|sdS |\  }}|
                    d	i           
                    d
          t           k    rdS dS )NFr   r   r   
statusLinett-statuslinecommand tuistatus_lineT)ospathisdirdirnameCLAUDE_SETTINGSexistsr   r   jsonloadget
isinstancedictr    JSONDecodeErrorr$   CODEX_STATUS_LINE)has_cc	has_codexr"   settingsslresult_parseds           r   is_setupr@      s   W]]27???;;<<F|,,I ) u 	osW=== (9Q<<( ( ( ( ( ( ( ( ( ( ( ( ( ( (l++Bb$'' ?266)CTCTCZXZ+[ u-. 	 	 	55	 #%% 	5	6::eR  $$]337HH 	54s7   /C8 B'C8 'B++C8 .B+/AC8 8DDc                  \   	 t          t          dd          5 } | D ]f}|                    d          rO|                    dd          d                                                             d          c cd d d            S g	 d d d            n# 1 swxY w Y   n# t
          $ r Y nw xY wd S )Nr   r   r   __version__=r   z"')r   HOOK_SCRIPT_PATH
startswithsplitstripr    )r"   lines     r   _installed_hook_versionrI      s?   "C'::: 	Fa F F??=11 F::c1--a06688>>uEEEE	F 	F 	F 	F 	F 	F 	F 	FFF	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F    4sA   B AB5B BB BB BB 
B)(B)c                  0    t                      t          k    S )N)rI   HOOK_VERSIONr   r   r   needs_updaterL      s    "$$44r   c                  R   t          t          dd          5 } |                     t                     d d d            n# 1 swxY w Y   t	          j        t          t	          j        t                    j        t          j        z  t          j	        z  t          j
        z             d S )Nwr   r   )r   rD   writeHOOK_SCRIPTr,   chmodstatst_modeS_IXUSRS_IXGRPS_IXOTH)r"   s    r   update_hookrW      s    	g	6	6	6 !	              Hrw'788@4<ORVR^^aeammnnnnns   ?AAFautoc                    t           j                            t           j                            t                              }t           j                            t                    }|s|st          j        d           d S | rt          j        d           |rt                       n| st          j        d           |rt                       d S | st          j        d           d S d S )NuH   [red]未检测到 Claude Code 或 Codex，请先安装其中之一[/red]u2   [dim]首次使用，正在配置状态栏...[/dim]u,   [dim]未检测到 Claude Code，跳过[/dim]u&   [dim]未检测到 Codex，跳过[/dim])r,   r-   r.   r/   r0   r1   r   r   print_setup_claude_setup_codex)rX   r9   r:   s      r   setupr]      s    W]]27???;;<<F|,,I ) `aaa LJKKK J 	JMHIII D 	DMBCCCCC	D 	Dr   c                     t          t          dd          5 } |                     t                     d d d            n# 1 swxY w Y   t	          j        t          t	          j        t                    j        t          j        z  t          j	        z  t          j
        z             i }t          j                            t                    rCt          t          dd          5 } t          j        |           }d d d            n# 1 swxY w Y   |                    d          }|rPd|                    d          pdvr7t#          j        d	           ||                    t(          i           t*          <   dt          d
|d<   t          t          dd          5 } t          j        || dd           d d d            n# 1 swxY w Y   t#          j        d           t#          j        d           d S )NrN   r   r   r   r&   r'   r(   r)   u=   [yellow]检测到已有 statusLine，备份后替换[/yellow])typer(      Findentensure_asciiu3   [green]✓[/green] Claude Code statusLine 已配置u'   [dim]重启 Claude Code 后生效[/dim])r   rD   rO   rP   r,   rQ   rR   rS   rT   rU   rV   r-   r1   r0   r2   r3   r4   r   rZ   
setdefault_BACKUP_KEY_PREV_SL_KEYdump)r"   r;   existings      r   r[   r[      sg   	g	6	6	6 !	              Hrw'788@4<ORVR^^aeammnnnH	w~~o&& $/3999 	$Qy||H	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ 	$ ||L))H FOHLL,C,C,IrJ FVWWW=EK,,\:&/<LMMH\	osW	5	5	5 =	(Aae<<<<= = = = = = = = = = = = = = = MHIIIM;<<<<<s3   ?AA$DD	D	G  GGc                  `   t                      } | sd S | \  }}|                    di                               d          }|t          k    rt          j        d           d S |tt          t          dd          5 }t          j        d|i|           d d d            n# 1 swxY w Y   t          
                    t          t                    |          }nKd|v r,|                    ddt          t                               }n|d	t          t                     d
z  }t          t          dd          5 }|                    |           d d d            n# 1 swxY w Y   t          j        d           |t          j        dt           d           t          j        d           d S )Nr*   r+   u8   [dim]Codex status_line 已是目标配置，跳过[/dim]rN   r   r   z[tui]z[tui]
z
[tui]

u.   [green]✓[/green] Codex status_line 已配置u   [dim]原配置已备份到: z[/dim]u!   [dim]重启 Codex 后生效[/dim])r$   r4   r8   r   rZ   r   CODEX_BACKUPr2   rg   	_SL_REGEXsubr   replacer   rO   )r=   r#   r?   oldr"   s        r   r\   r\      s,   !!F OGV
**UB


#
#M
2
2C
 PQQQ
 H,g666 	/!I}c*A...	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/-- 12C D DgNN	G	 H//'+[5FGX5Y5Y+[+[\\G01BCCGGGG	lC'	2	2	2 a	               MCDDD
 KI\IIIJJJM566666s$   ;BB#&B#:EE #E c                  H   t           j                            t           j                            t                              } t           j                            t                    }| rt                       |rt                       | s|st          j
        d           d S d S d S )Nu-   [dim]未检测到 Claude Code 或 Codex[/dim])r,   r-   r.   r/   r0   r1   r   _unsetup_claude_unsetup_codexr   rZ   )r9   r:   s     r   unsetuprs     s    W]]27???;;<<F|,,I   G) GEFFFFFG G G Gr   c                  `   t           j                            t                    r5t          j        t                     t          j        dt                      t           j                            t                    sd S t          t          dd          5 } t          j
        |           }d d d            n# 1 swxY w Y   |                    d          }t          |t                    rd|                    d          pdvrt          j        d	           d S |                    t          i                               t                    }t          |t                    r||d<   t          j        d
           n*|                    dd            t          j        d           |                    t                    }t          |t                    r%|                    t          d            |s|t          = t          t          dd          5 } t          j        || dd           d d d            n# 1 swxY w Y   t           j                            d          }t           j                            |          r-t          j        |           t          j        d|            d S d S )Nu   [green]✓[/green] 已删除: r   r   r   r&   r'   r(   r)   uF   [dim]当前 statusLine 不是 tt-statusline，保留现有配置[/dim]u<   [green]✓[/green] Claude Code statusLine 已恢复原配置u3   [green]✓[/green] Claude Code statusLine 已移除rN   r`   Fra   z~/.claude/tt-status.jsonu$   [green]✓[/green] 已删除缓存: )r,   r-   r1   rD   remover   rZ   r0   r   r2   r3   r4   r5   r6   re   rf   poprg   
expanduser)r"   r;   r<   previousbackupstatus_files         r   rq   rq     s   	w~~&'' K
	"###I7GIIJJJ7>>/** 	osW	5	5	5  9Q<<                              
l	#	#Bb$ ?266);L;L;RPR#S ^___||K,,00>>H(D!! N!)UVVVV\4(((LMMM\\+&&F&$ &

<&&& 	&%	osW	5	5	5 =	(Aae<<<<= = = = = = = = = = = = = = = '$$%?@@K	w~~k"" L
	+J[JJKKKKKL Ls$   B88B<?B<H88H<?H<c                  "   t                      } | sd S | \  }}|                    di                               d          d S t          j                            t
                    rt          t
          dd          5 }t          j        |                              dg           }d d d            n# 1 swxY w Y   t          
                    t          |          |          }t          j        t
                     t          j        d           n6t          j
        dd|t          j        	          }t          j        d
           t          t"          dd          5 }|                    |           d d d            d S # 1 swxY w Y   d S )Nr*   r+   r   r   r   u7   [green]✓[/green] Codex status_line 已恢复原配置zstatus_line\s*=\s*\[.*?\]\n?r)   )flagsu.   [green]✓[/green] Codex status_line 已移除rN   )r$   r4   r,   r-   r1   rk   r   r2   r3   rl   rm   r   ru   r   rZ   reDOTALLr   rO   )r=   r#   r?   r"   	old_itemss        r   rr   rr   F  s   !!F OGVzz%  // 	w~~l## I,g666 	<!	!((;;I	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	< 	<-- 1) < <gFF
	,PQQQQ&8"gRYWWWGHHH	lC'	2	2	2 a	                 s$   >)B33B7:B7!FFF)r	   N)F)&r2   r,   r}   rR   r   	ui.tablesr   r-   rw   r0   rD   r   rk   rK   re   rf   compiler~   rl   r8   rP   liststrr   tupler6   r$   boolr@   rI   rL   rW   r]   r[   r\   rs   rq   rr   r   r   r   <module>r      s>    				 				        '$$%>??7%%&BCC w!!"899w!!";<<#BJ3RY??	   hZ*T#Y *3 * * * *
E#t),t3    $    0t    5d 5 5 5 5o o o oD D D D D D D0= = = =07 7 7 7>	G 	G 	G 	G$L $L $L $LN     r   