SLOPSHOPPER

usage-band

프롬프트 바로 위에 Claude(5시간·주간·모델별 주간·컨텍스트)와 Codex 사용량을 열을 맞춘 막대로 보여 줍니다

newbandcommandtoastprocessnetwork
v0.6.6no licenseupdated 2026-10-06kgrvGRECO/woo-mods/usage-band
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · usage-band
› fix the failing auth test and add an audit log call ╭────────────╮ │ usage-band │ ⏺ Read(src/auth.ts) │ 사용량 띠: 한 줄 │ ⎿ Read 6 lines ╰────────────╯ ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM › /usagebar Claude 5시간 31% ctx 49% │ Codex 이 PC에 Codex 사용 기록이 없어요 ⟨Claude Code's own drawing⟩ ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Band
Claude 5시간 31% ctx 49% │ Codex 이 PC에 Codex 사용 기록이 없어요 ⟨Claude Code's own drawing⟩
README

woo-mods — Claude Code mods 두 개

mod하는 일명령
usage-band프롬프트 바로 위에 Claude(5시간·주간·Fable 등 모델별 주간·컨텍스트)와 Codex 사용량 막대. 두 줄의 열이 맞춰져 있음/usagebar 두 줄 → 한 줄 → 숨김
pocket-pet바탕화면에 사는 픽셀 펫 "클로"(주황 몸·민트 스카프). Claude가 생각·작업·허락 대기·완료할 때 반응하고, 마우스로 끌어 옮길 수 있음. 사용량 띠와는 따로 동작/pet 켜기, /pet pat 쓰다듬기, /pet 끄기

필요: Claude Code v2.1.287 이상 (claude --version). 터미널과 데스크톱 앱의 Code 탭에서 보입니다(VS Code 확장 채팅창에서는 안 그려짐).

설치 (Windows)

다른 PC에서는 GitHub 저장소(kgrvGRECO/woo-mods)를 마켓플레이스로 추가합니다. Claude Code에서:

/plugin marketplace add kgrvGRECO/woo-mods
/plugin install usage-band@woo-mods
/plugin install pocket-pet@woo-mods
/reload-plugins

새 버전이 올라오면 /plugin marketplace update woo-mods → /plugin update pocket-pet@woo-mods(또는 usage-band) → /reload-plugins. 바탕화면 클로에는 Python 3의 pythonw가 필요합니다(없으면 /pet에서 안내가 뜹니다).

이 PC(개발 폴더 C:\dev\개발용\mods)에서는 폴더를 마켓플레이스로 씁니다: /plugin marketplace add C:\dev\개발용\mods 뒤 위와 같이 설치. 설정 바꾸기(선택): /plugin configure pocket-pet@woo-mods — 이름, 자동으로 띄우기(on·off), pythonw 경로

한 번만 시험해 보려면 설치 없이: claude --plugin-dir C:\dev\개발용\mods\pocket-pet --plugin-dir C:\dev\개발용\mods\usage-band

수정한 뒤 반영: 이 폴더에서 Claude Code로 고치면 저절로 반영됩니다. 프로젝트 훅(.claude/settings.json)이 고친 파일이 속한 mod를 tools/sync_mods.py로 플러그인 캐시에 복사하고 등록을 고쳐, 데스크톱 앱이 열린 Code 세션 모두에 다시 불러오기를 보냅니다(desktop/을 고치면 바탕화면 클로도 새 코드로 다시 뜹니다). 직접 편집기로 고쳤으면 한 번 실행하세요: python tools\sync_mods.py (하나만: python tools\sync_mods.py pocket-pet). 버전을 올리지 않아도 반영됩니다.

  • 데스크톱 앱은 플러그인의 실제 위치가 캐시 폴더 안에 있어야만 불러옵니다. 그래서 개발 폴더를 링크로 직접 잇는 대신 복사합니다.
  • 이미 열린 세션은 세션을 열 때 정해진 버전 폴더에서 계속 읽습니다. 등록된 버전을 바꿔도 그 세션은 옮겨 가지 않아서, 예전에는 /reload-plugins를 해도 옛 코드가 다시 올라왔습니다. 그래서 동기화 스크립트는 지금 등록된 버전 폴더뿐 아니라 돌고 있는 세션이 쓰는 버전 폴더(Claude Code가 .in_use 표시를 남긴 곳) 전부에 최신을 넣습니다. 그러면 어느 세션이든 다시 불러올 때 새 코드가 올라갑니다.
  • 다시 불러오기는 세션이 쉬고 있을 때 적용됩니다. 그 세션에서 Claude가 작업 중이면 턴이 끝난 뒤에 올라갑니다. 1분 안에 연달아 고치면 앱이 모았다가 1분 뒤 한 번에 적용합니다.

알아 둘 점

  • Claude 수치의 출처. 5시간·주간·컨텍스트는 Claude Code가 응답마다 알려 주는 값입니다. 여기에 더해 1분마다, 그리고 턴이 끝날 때마다(30초 간격 안이면 건너뜀) Claude Code의 /usage가 쓰는 사용량 API를 직접 받아 Fable 같은 모델별 주간 한도를 채우고 5시간·주간도 최신으로 맞춥니다. 자격 증명은 Claude Code가 핸들로 붙여 주므로 mod는 토큰을 보지 않습니다. 세션이 여럿 열려 있으면 한 세션이 받은 값을 나머지가 저장소에서 가져다 쓰므로 API는 전체로 1분에 한 번쯤만 부릅니다. API가 거절하면(429 등) 알려 준 시간만큼 쉬었다 다시 받고, 그동안 Fable 값이 15분 넘게 묵으면 "Fable 20분 전 기록 · API 429"처럼 까닭이 붙습니다(마지막 시도 결과는 ~/.claude/plugins/store/usage-band_*.json의 claudeFetch에도 남습니다). 로그인 없이 쓰거나 API를 못 받을 때만 상태줄(awesome-statusline)이 남기는 %TEMP%\.claude_usage_cache를 대신 읽고, 그마저 오래되면 "몇 분 전 기록"이 붙습니다.
  • Claude 한도는 이번 세션의 첫 응답 뒤에 채워집니다. 그 전에는 지난 세션에서 본 값을 "몇 분 전 기록"으로 보여 줍니다.
  • Codex 사용량은 Codex CLI의 앱 서버(codex app-server)에 1분마다 물어서 받습니다. Codex가 /status에 보여 주는 것과 같은 값이고, 인증은 Codex가 스스로 하므로 토큰을 만지지 않습니다. node와 codex 명령이 있어야 하며(npm으로 Codex를 깔았으면 둘 다 있음), 못 받을 때만 이 PC의 %USERPROFILE%\.codex\sessions 기록(Codex를 마지막으로 쓴 시점의 값)을 읽고 "몇 분 전 기록"을 붙입니다. 리셋 시각이 지난 창은 0%로 표시합니다.
  • 바탕화면 클로는 Claude Code를 열면 함께 뜹니다(Python 3의 pythonw가 PATH에 있어야 함, 없으면 /plugin configure pocket-pet@woo-mods에서 경로 지정). 마우스를 올리면 아래에 입력 영역이 열립니다: Code 또는 대화(일반 Claude 대화)를 고르고 적어서 Enter를 누르면 Claude 데스크톱 앱에서 이어집니다. Code에서는 폴더 칩을 눌러 열린 세션에 이어서(그 세션에 바로 들어감) 또는 새 세션 폴더(그 폴더에서 새 Code 세션)를 고릅니다. 열린 세션으로 보내기는 pocket-pet 0.5.0 이상이 돌고 있는 세션에서만 됩니다(목록에도 그런 세션만 나옴). 새 세션 폴더로 보내면 클로가 Claude Code CLI(claude)로 그 폴더에서 첫 턴을 화면 없이 돌린 뒤(보통 10~30초, 클로가 "생각하는 중"으로 보여 줌) 그 세션을 데스크톱 앱에 들여와 바로 엽니다. 첫 턴은 화면이 없어서 허락을 물을 수 없으므로, 읽기만으로 답할 수 있는 질문은 바로 답해 두고, 파일 수정·명령 실행이 필요한 요청은 계획만 적어 두었다가 앱에서 "진행"이라고 하면 시작합니다(그때부터는 평소처럼 허락을 묻습니다). CLI가 없으면 앱의 새 세션 작성 화면에 글만 채워 두므로 Enter로 시작하세요. CLI 경로를 직접 지정하려면 desktop.json에 "claude": "경로"를 적습니다. 말하기는 Windows 음성 입력(Win+H)을 켭니다(설정 → 시간 및 언어 → 음성에서 한국어 음성 입력이 켜져 있어야 함). 왼쪽 버튼으로 끌어 옮기고, 클릭하면 Claude 데스크톱 앱이 앞으로 나옵니다(꺼져 있으면 실행). 오른쪽 클릭하면 메뉴(Claude 열기 · 쓰다듬기 · 말풍선 끄고 켜기 · 크기 작게/보통/크게 · 끄기)가 나옵니다. 자리와 크기는 %USERPROFILE%\.claude\clo\desktop.json에 남습니다.
  • 세션이 여럿이면 허락을 기다리는 세션을 먼저, 그다음 가장 최근에 바뀐 세션을 따릅니다. Claude Code를 모두 닫고 30분이 지나면 클로도 스스로 꺼집니다.
  • 펫 그림을 바꾸려면 새 시안 묶음(clo-pet-assets)을 풀고 python pocket-pet ools\make-frames.py <폴더>(Pillow 필요)를 실행하세요.
  • mod는 Claude Code와 같은 권한으로 실행됩니다. 이 두 mod가 하는 일: 네트워크는 usage-band가 Claude 사용량 API(api.anthropic.com/api/oauth/usage, Claude Code의 /usage와 같은 곳) 한 군데만 부르며, 자격 증명은 Claude Code가 핸들로 붙여 주어 mod는 토큰을 보지 않습니다. 실행하는 프로그램은 node(Codex 앱 서버에 한도를 묻는 작은 스크립트), codex app-server(그 스크립트가 띄웠다 닫음), PowerShell(큰 Codex 기록에서 마지막 줄만 뽑을 때, 바탕화면 클로를 띄울 때), pythonw(바탕화면 클로), 그리고 클로가 새 세션을 열 때의 claude -p입니다. 파일은 Codex 기록·상태줄 캐시 읽기, 클로 상태 파일(~/.claude/clo) 쓰기, 자체 저장소에 설정 저장. claude plugin validate .\usage-band 로 직접 확인할 수 있습니다.
  • mods API는 아직 얼리 액세스라 Claude Code 업데이트 때 깨질 수 있습니다. 그러면 claude --debug의 로그를 Claude에게 보여 주세요.
  • 클로의 말풍선과 입력 카드 글꼴은 Neo둥근모(SIL Open Font License 1.1, pocket-pet/desktop/fonts/LICENSE-neodgm.txt)입니다. 프로그램 안에서만 불러오며 Windows에 설치하지 않습니다. 사용량 띠의 데스크톱 패널도 같은 글꼴(woff2, usage-band/fonts/)을 그림 안에 넣어 씁니다.
Source 6 files
hooks/register.tsx 568 lines
1// usage-band: 프롬프트 바로 위 띠에 Claude와 Codex 사용량을 보여 주는 mod.
2//
3//   Claude  5시간 █▌░░░░░░░░  3% 3시간 5분 후   주간 ███████▋░░ 77% 1일 13시간 후   Fable ██████████ 100% 1일 후   컨텍스트 19%
4//   Codex                                     주간 ████░░░░░░ 40% 4일 19시간 후                                  39분 전 기록
5//
6// 열마다 이름표·막대·퍼센트·리셋 시각의 자리를 맞춰 두 줄이 위아래로 정렬된다. 데스크톱 앱에서는
7// 글꼴이 고정폭이 아니어서 두 줄을 SVG 한 장(panel.ts)으로 그리고, 터미널에서는 칸 수를 세어 맞춘다.
8//
9// Claude 5시간·주간·컨텍스트는 Claude Code가 응답마다 주는 값이고, 모델별 주간 한도(Fable 등)와 그 사이의
10// 갱신은 /usage 가 쓰는 사용량 API를 1분마다 세션의 자격 증명 핸들로 직접 받아서(claude-cache.ts) 채운다.
11// 열린 세션이 여럿이면 저장소($.store)를 같이 쓰므로 한 세션이 받은 값을 나머지가 가져다 쓰고, API가 거절하면
12// (429 등) 알려 준 만큼 쉬었다 다시 받는다. 못 받은 까닭은 저장소 claudeFetch에 남기고 띠의 메모에도 붙인다.
13// API를 못 쓰면(로그인 없음·게이트웨이) 상태줄이 남긴 캐시 파일로 대신한다. Codex 수치는 Codex CLI의 앱 서버에
14// 물어서(hooks/codex-limits.mjs, 공식 경로) 받고, 그게 안 되면 Codex가 이 PC에 남긴 세션 기록에서 읽는다.
15// /usagebar 로 두 줄 → 한 줄 → 숨김을 돌아가며 바꾼다.
16
17import type { EngineInterface, Register, SessionRateLimit } from 'claude-code'
18
19import { parseClaudeCache, type ClaudeCache } from './claude-cache'
20import { effectivePct, lastSnapshot, snapshotFromAppServer, type CodexSnapshot } from './codex'
21import { agoText, BAR_WIDTH, barParts, colorFor, columnsOf, cellWidth, padCells, padCellsStart, pctText, resetText, type BandRow, type Meter } from './format'
22import { panelSvg } from './panel'
23
24type Layout = 'full' | 'compact' | 'hidden'
25type ClaudeFigures = { limits: SessionRateLimit[]; at: number }
26/** 사용량 API를 마지막으로 받으려 한 결과. 저장소 claudeFetch에도 남겨서 띠가 옛 값을 보일 때 까닭을 찾을 수 있게 한다 */
27type FetchNote = {
28  at: number
29  session: string
30  /** ok 받음 · no-auth 자격 증명 없음 · http 거절(status) · shape 응답 모양이 다름 · error 연결 실패 */
31  outcome: 'ok' | 'no-auth' | 'http' | 'shape' | 'error'
32  status?: number
33  detail?: string
34  /** 다음에 다시 받아 볼 때(ms) */
35  retryAt?: number
36}
37
38const LAYOUTS: Layout[] = ['full', 'compact', 'hidden']
39const BIG_FILE = 3_500_000 // $.fs.read 한도(4 MiB)보다 작게
40const CLAUDE_LABEL: Record<string, string> = {
41  five_hour: '5시간',
42  seven_day: '주간',
43  spend_limit: '지출 한도',
44}
45const CLAUDE_COLOR = '#d97757'
46const CODEX_COLOR = '#3b6fe0'
47const STALE_MS = 15 * 60_000 // 캐시가 이보다 오래되면 "몇 분 전"을 붙인다
48// 사용량 API: Claude Code의 /usage 와 같은 곳. 자격 증명은 엔진이 핸들로 붙이므로 mod는 토큰을 보지 않는다
49const USAGE_URL = 'https://api.anthropic.com/api/oauth/usage'
50const USAGE_HEADERS = { 'anthropic-beta': 'oauth-2025-04-20', accept: 'application/json' }
51const FETCH_GAP_MS = 30_000 // 이보다 자주는 받지 않는다(턴이 연달아 끝나도)
52const NO_AUTH_RETRY_MS = 10 * 60_000 // 자격 증명이 없다고 하면 이만큼 뒤에 다시 물어본다
53const FAIL_RETRY_MS = 5 * 60_000 // 사용량 API가 거절하거나(429·5xx) 끊기면 이만큼 뒤에 다시 받는다(Retry-After가 있으면 그만큼)
54const SHARED_FRESH_MS = 50_000 // 다른 세션이 이 안에 받아 둔 값이 저장소에 있으면 직접 받지 않는다
55const CODEX_LIVE_GAP_MS = 30_000 // Codex 앱 서버에는 이보다 자주 묻지 않는다
56const CODEX_LIVE_RETRY_MS = 10 * 60_000 // 앱 서버를 못 띄우면(node·codex 없음) 이만큼 뒤에 다시 해 본다
57
58// 모듈 상태(다시 불러오면 처음부터; 남길 값은 $.store에)
59let layout: Layout = 'full'
60let claude: ClaudeFigures | undefined
61let isClaudeFromStore = false
62let contextPct: number | undefined
63let codex: CodexSnapshot | undefined
64let codexHome: string | undefined
65let configuredHome = ''
66let isReading = false
67let cachePath = '' // Claude 사용량 캐시 파일(비어 있으면 아직 못 찾음)
68let configuredCache = ''
69let claudeCache: ClaudeCache | undefined
70let lastFetchAt = 0 // 사용량 API를 마지막으로 받은(또는 시도한) 때
71let noAuthUntil = 0 // 이때까지는 자격 증명을 다시 묻지 않는다
72let failUntil = 0 // 사용량 API가 거절한 뒤 이때까지는 다시 받지 않는다
73let lastFetch: FetchNote | undefined // 사용량 API를 마지막으로 받으려 한 결과
74let lastCodexLiveAt = 0 // Codex 앱 서버에 마지막으로 물은 때
75let codexLiveDownUntil = 0 // 이때까지는 앱 서버 대신 세션 기록만 읽는다
76let lastBandSize = ''
77let sessionTag = '' // 이 세션의 ID 앞 8자: 여러 세션이 같은 저장소를 쓰므로 기록에 누가 썼는지 남긴다
78// 이미 읽은 기록 파일: 크기·수정 시각이 같으면 다시 읽지 않는다
79const parsed = new Map<string, { size: number; mtimeMs: number; snap: CodexSnapshot | undefined }>()
80
81function redraw($: EngineInterface) {
82  $.ui.invalidate('ui.render')
83}
84
85// ── Codex 기록 찾기 ────────────────────────────────────────────────
86async function findCodexHome($: EngineInterface): Promise<string | undefined> {
87  if (configuredHome) return configuredHome
88  const fromEnv = await $.env.get('CODEX_HOME')
89  if (fromEnv) return fromEnv
90  const profile = (await $.env.get('USERPROFILE')) ?? (await $.env.get('HOME'))
91  if (!profile) return undefined
92  return profile + (profile.includes('\\') ? '\\' : '/') + '.codex'
93}
94
95/** 큰 파일은 통째로 읽지 않고 rate_limits가 든 마지막 줄만 가져온다 */
96async function lastRateLine($: EngineInterface, path: string, isWindows: boolean): Promise<string> {
97  const argv = isWindows
98    ? [
99        'powershell.exe',
100        '-NoProfile',
101        '-NonInteractive',
102        '-Command',
103        `(Select-String -LiteralPath '${path.replace(/'/g, "''")}' -Pattern '"rate_limits":{' -SimpleMatch | Select-Object -Last 1).Line`,
104      ]
105    : ['sh', '-c', 'grep -F \'"rate_limits":{\' "$1" | tail -n 1', 'sh', path]
106  try {
107    const r = await $.process.run(argv, { timeoutMs: 15_000 })
108    return r.stdout
109  } catch {
110    return ''
111  }
112}
113
114async function readCodex($: EngineInterface): Promise<CodexSnapshot | undefined> {
115  codexHome ??= await findCodexHome($)
116  if (!codexHome) return undefined
117  const isWindows = codexHome.includes('\\') || /^[A-Za-z]:/.test(codexHome)
118  const sep = isWindows ? '\\' : '/'
119  const join = (...parts: string[]) => parts.join(sep)
120  const sessions = join(codexHome, 'sessions')
121  if (!(await $.fs.exists(sessions))) return undefined
122
123  const namesDesc = async (dir: string, pattern: RegExp) =>
124    (await $.fs.list(dir))
125      .filter(x => x.kind === 'dir' && pattern.test(x.name))
126      .map(x => x.name)
127      .sort()
128      .reverse()
129
130  // 최근 날짜 폴더부터 rollout 파일을 모은다(최대 7일치, 8개)
131  const files: { path: string; size: number; mtimeMs: number }[] = []
132  let days = 0
133  outer: for (const y of await namesDesc(sessions, /^\d{4}$/)) {
134    for (const m of await namesDesc(join(sessions, y), /^\d{2}$/)) {
135      for (const d of await namesDesc(join(sessions, y, m), /^\d{2}$/)) {
136        const dir = join(sessions, y, m, d)
137        for (const f of await $.fs.list(dir)) {
138          if (f.kind === 'file' && /^rollout-.*\.jsonl$/.test(f.name)) {
139            files.push({ path: join(dir, f.name), size: f.size, mtimeMs: f.mtimeMs })
140          }
141        }
142        days += 1
143        if (files.length >= 8 || days >= 7) break outer
144      }
145    }
146  }
147  files.sort((a, b) => b.mtimeMs - a.mtimeMs)
148
149  // 가장 최근 파일부터, rate_limits가 실제로 들어 있는 첫 스냅숏을 쓴다
150  for (const f of files.slice(0, 8)) {
151    const seen = parsed.get(f.path)
152    let snap = seen?.snap
153    if (!seen || seen.size !== f.size || seen.mtimeMs !== f.mtimeMs) {
154      const text = f.size <= BIG_FILE ? await $.fs.read(f.path).catch(() => '') : await lastRateLine($, f.path, isWindows)
155      snap = lastSnapshot(text)
156      parsed.set(f.path, { size: f.size, mtimeMs: f.mtimeMs, snap })
157    }
158    if (snap) {
159      if (!snap.at) snap.at = f.mtimeMs
160      return snap
161    }
162  }
163  return undefined
164}
165
166/** Codex 앱 서버에 지금 한도를 묻는다(공식 경로, hooks/codex-limits.mjs). 못 받으면 undefined */
167async function readCodexLive($: EngineInterface): Promise<CodexSnapshot | undefined> {
168  const now = await $.clock.now()
169  if (now < codexLiveDownUntil || now - lastCodexLiveAt < CODEX_LIVE_GAP_MS) return undefined
170  lastCodexLiveAt = now
171  const root = $.plugin.root
172  const script = [root, 'hooks', 'codex-limits.mjs'].join(root.includes('\\') ? '\\' : '/')
173  try {
174    const r = await $.process.run(['node', script], { timeoutMs: 20_000 })
175    const last = r.stdout.trim().split('\n').pop() ?? ''
176    const o = JSON.parse(last) as { ok?: boolean; at?: number; result?: unknown }
177    if (!o.ok) {
178      codexLiveDownUntil = now + CODEX_LIVE_RETRY_MS
179      return undefined
180    }
181    return snapshotFromAppServer(o.result, typeof o.at === 'number' ? o.at : now)
182  } catch {
183    codexLiveDownUntil = now + CODEX_LIVE_RETRY_MS // node나 codex가 없거나 시험 엔진
184    return undefined
185  }
186}
187
188async function refreshCodex($: EngineInterface) {
189  if (isReading) return
190  isReading = true
191  try {
192    // 앱 서버가 답하면 그게 지금 값이고, 아니면 Codex가 남긴 세션 기록(마지막으로 쓴 때의 값)
193    const snap = (await readCodexLive($)) ?? (codex?.source === 'live' ? undefined : await readCodex($))
194    if (snap) {
195      codex = snap
196      await $.store.set('codex', snap)
197    }
198  } catch {
199    // 기록 폴더를 못 읽어도 띠는 계속 그린다
200  } finally {
201    isReading = false
202    redraw($)
203  }
204}
205
206// ── Claude 수치 ───────────────────────────────────────────────────
207/** 상태줄이 남기는 사용량 캐시: %TEMP%\.claude_usage_cache(Git Bash의 /tmp) 또는 /tmp */
208async function findCachePath($: EngineInterface): Promise<string> {
209  if (configuredCache) return configuredCache
210  const temp = (await $.env.get('TEMP')) ?? (await $.env.get('TMP'))
211  const candidates = [temp ? temp + (temp.includes('\\') ? '\\' : '/') + '.claude_usage_cache' : '', '/tmp/.claude_usage_cache']
212  for (const c of candidates) if (c && (await $.fs.exists(c).catch(() => false))) return c
213  return ''
214}
215
216const isCache = (v: unknown): v is ClaudeCache => !!v && typeof v === 'object' && typeof (v as ClaudeCache).at === 'number' && Array.isArray((v as ClaudeCache).scoped)
217
218/** 다른 세션이 같은 저장소에 받아 둔 값을 가져온다. 1분 안에 API에서 받은 값이면 true(직접 받을 필요가 없다) */
219async function adoptShared($: EngineInterface, now: number): Promise<boolean> {
220  const shared = await $.store.get('claudeCache').catch(() => undefined)
221  if (!isCache(shared)) return false
222  if (shared.at > (claudeCache?.at ?? 0)) claudeCache = shared
223  return shared.source === 'api' && now - shared.at < SHARED_FRESH_MS
224}
225
226async function noteFetch($: EngineInterface, note: Omit<FetchNote, 'session'>) {
227  lastFetch = { ...note, session: sessionTag }
228  await $.store.set('claudeFetch', lastFetch).catch(() => undefined)
229}
230
231/** 거절당한 뒤 다시 받기까지: Retry-After(초)가 있으면 그만큼(1분~30분), 없으면 5분 */
232function retryGap(headers: Record<string, string>): number {
233  const sec = Number(headers['retry-after'])
234  if (!Number.isFinite(sec) || sec <= 0) return FAIL_RETRY_MS
235  return Math.min(30 * 60_000, Math.max(60_000, sec * 1000))
236}
237
238/** 사용량 API에서 직접 받는다(5시간·주간·모델별 주간). 받았으면(또는 다른 세션이 방금 받은 값을 썼으면) true,
239 *  자격 증명이 없거나 실패하면 false */
240async function fetchClaudeUsage($: EngineInterface): Promise<boolean> {
241  const now = await $.clock.now()
242  if (now - lastFetchAt < FETCH_GAP_MS) return claudeCache?.source === 'api'
243  // 세션이 여럿이면 저장소를 같이 쓴다: 누군가 방금 받았으면 그 값을 쓰고 API를 세션 수만큼 두드리지 않는다
244  if (await adoptShared($, now)) return true
245  if (now < noAuthUntil || now < failUntil) return claudeCache?.source === 'api'
246  lastFetchAt = now
247  let auth: { handle: string } | null = null
248  try {
249    auth = await $.session.authorize()
250  } catch {
251    auth = null // 시험 엔진처럼 자격 증명을 다루지 않는 곳
252  }
253  if (!auth) {
254    noAuthUntil = now + NO_AUTH_RETRY_MS
255    await noteFetch($, { at: now, outcome: 'no-auth', retryAt: noAuthUntil })
256    return false
257  }
258  try {
259    const r = await $.http.fetch(USAGE_URL, { auth: auth.handle, headers: USAGE_HEADERS })
260    if (!r.ok) {
261      failUntil = now + retryGap(r.headers)
262      await noteFetch($, { at: now, outcome: 'http', status: r.status, detail: r.text.slice(0, 200), retryAt: failUntil })
263      return false
264    }
265    const next = parseClaudeCache(r.text, now)
266    if (!next) {
267      failUntil = now + FAIL_RETRY_MS
268      await noteFetch($, { at: now, outcome: 'shape', detail: r.text.slice(0, 200), retryAt: failUntil })
269      return false
270    }
271    claudeCache = { ...next, source: 'api' }
272    await $.store.set('claudeCache', claudeCache)
273    await noteFetch($, { at: now, outcome: 'ok' })
274    return true
275  } catch (err) {
276    failUntil = now + FAIL_RETRY_MS
277    await noteFetch($, { at: now, outcome: 'error', detail: String(err).slice(0, 200), retryAt: failUntil })
278    return false // 네트워크가 막혀도 띠는 계속 그린다
279  }
280}
281
282/** 상태줄이 남긴 캐시 파일에서 읽는다(API를 못 쓸 때의 대안) */
283async function readClaudeCacheFile($: EngineInterface) {
284  try {
285    cachePath ||= await findCachePath($)
286    if (!cachePath) return
287    const st = await $.fs.stat(cachePath)
288    if (claudeCache && claudeCache.at >= st.mtimeMs) return // API 값이나 같은 파일을 이미 가졌다
289    const next = parseClaudeCache(await $.fs.read(cachePath), st.mtimeMs)
290    if (next) {
291      claudeCache = { ...next, source: 'file' }
292      await $.store.set('claudeCache', claudeCache)
293    }
294  } catch {
295    // 캐시가 없거나 모양이 달라도 띠는 계속 그린다
296  }
297}
298
299async function refreshClaudeCache($: EngineInterface) {
300  if (!(await fetchClaudeUsage($))) await readClaudeCacheFile($)
301}
302
303async function takeClaude($: EngineInterface, limits: SessionRateLimit[], ctx: number | undefined) {
304  if (ctx !== undefined) contextPct = ctx
305  if (limits.length > 0) {
306    claude = { limits, at: await $.clock.now() }
307    isClaudeFromStore = false
308    await $.store.set('claude', claude)
309  }
310  redraw($)
311}
312
313export const register: Register = (on, options) => {
314  layout = options.layout === 'compact' ? 'compact' : 'full'
315  configuredHome = typeof options.codex_home === 'string' ? options.codex_home.trim() : ''
316  configuredCache = typeof options.usage_cache === 'string' ? options.usage_cache.trim() : ''
317
318  on('session.start', async ($, e, next) => {
319    const result = await next(e)
320    // 어느 폴더의 usage-band가 어느 세션에 올라왔는지(설치본 · 개발 폴더) 남긴다. 열린 세션은 열 때 정해진
321    // 버전 폴더를 계속 쓰므로, 띠가 옛 모양이면 여기 적힌 폴더부터 본다
322    try {
323      sessionTag = (await $.session.id()).slice(0, 8)
324    } catch {
325      sessionTag = 'test' // 시험 엔진처럼 세션 ID가 없는 곳
326    }
327    void $.store.set('loaded', { root: $.plugin.root, session: sessionTag, at: await $.clock.now() })
328
329    const savedLayout = await $.store.get('layout')
330    if (savedLayout === 'full' || savedLayout === 'compact' || savedLayout === 'hidden') layout = savedLayout
331
332    // 이번 세션의 첫 응답 전에는 지난 세션에서 본 값을 보여 준다
333    const savedClaude = (await $.store.get('claude')) as ClaudeFigures | undefined
334    if (savedClaude && Array.isArray(savedClaude.limits)) {
335      claude = savedClaude
336      isClaudeFromStore = true
337    }
338    const savedCodex = (await $.store.get('codex')) as CodexSnapshot | undefined
339    if (savedCodex && typeof savedCodex.at === 'number') codex = savedCodex
340    const savedCache = (await $.store.get('claudeCache')) as ClaudeCache | undefined
341    if (savedCache && typeof savedCache.at === 'number' && Array.isArray(savedCache.scoped)) claudeCache = savedCache
342
343    const usage = await $.session.usage()
344    await takeClaude($, usage.rateLimits, usage.context.percent)
345
346    void refreshClaudeCache($).then(() => refreshCodex($))
347    $.clock.every(60_000, () => {
348      // 사용량 API·Codex 기록 다시 받기 + 남은 시간 글자 갱신
349      void refreshClaudeCache($).then(() => refreshCodex($))
350    })
351
352    try {
353      await $.command.register({
354        name: 'usagebar',
355        description: '사용량 띠 모양 바꾸기 (두 줄 → 한 줄 → 숨김)',
356        immediate: true,
357      })
358    } catch {
359      // 같은 이름의 명령이 이미 있으면 명령 없이 띠만 그린다
360    }
361    return result
362  })
363
364  // 응답마다 한도·컨텍스트가 움직이면 엔진이 알려 준다
365  on('session.measure', async ($, e, next) => {
366    await takeClaude($, e.rateLimits, e.context.percent)
367    return next(e)
368  })
369
370  // 한 턴이 끝나면 사용량 API(30초 간격 안이면 건너뜀)와 Codex 쪽도 한 번 더 받는다
371  on('turn.complete', async ($, e, next) => {
372    const result = await next(e)
373    if (!e.agentId) void refreshClaudeCache($).then(() => refreshCodex($))
374    return result
375  })
376
377  on('command.run', { command: 'usagebar' }, async ($, e) => {
378    const asked = e.args.trim()
379    layout = (LAYOUTS as string[]).includes(asked)
380      ? (asked as Layout)
381      : (LAYOUTS[(LAYOUTS.indexOf(layout) + 1) % LAYOUTS.length] ?? 'full')
382    await $.store.set('layout', layout)
383    redraw($)
384    $.ui.toast(layout === 'full' ? '사용량 띠: 두 줄' : layout === 'compact' ? '사용량 띠: 한 줄' : '사용량 띠: 숨김 (/usagebar 로 다시 켜기)')
385    return {}
386  })
387
388  // ── 그리기 ────────────────────────────────────────────────────────
389  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
390    if (e.props.hasSurvey || layout === 'hidden') return next(e)
391
392    const { Box, Text } = $.ui.resolve(e)
393    const now = await $.clock.now()
394    const rows = rowsOf(now)
395    const cols = e.props.bodyColumns
396    const isTerminal = e.surface === 'terminal'
397
398    let mine
399    if (layout === 'full' && !isTerminal) {
400      // 데스크톱·편집기: 두 줄을 SVG 한 장으로(열이 정확히 맞는다)
401      // 크기를 정하지 않으면 그림의 너비(넉넉한 기본값)에서 회색 띠 너비까지 맞춰 그려진다
402      const { Svg } = $.ui.resolve(e)
403      const alt = rows.map(r => `${r.name} ${r.meters.filter(m => m?.pct !== undefined).map(m => `${m?.label} ${pctText(m?.pct ?? 0)}`).join(', ')}`).join(' / ')
404      let drawn: { width: number; height: number; length: number } | undefined
405      let problem = ''
406      try {
407        const { svg, width, height } = panelSvg(rows, now)
408        drawn = { width, height, length: svg.length }
409        mine = <Svg source={svg} alt={alt} width={width} height={height} />
410      } catch (err) {
411        // 그림을 못 만들면 띠가 비지 않게 한 줄로 대신 보여 준다
412        problem = String(err)
413        mine = <Text>{alt}</Text>
414      }
415      // 띠 크기와 그린 결과를 남겨 두면 안 보일 때 원인을 찾을 수 있다
416      const seen = `${cols}x${e.viewport.columns}x${e.props.maxRows}|${drawn?.height}|${problem}`
417      if (seen !== lastBandSize) {
418        lastBandSize = seen
419        void $.store.set('desktopBand', { bodyColumns: cols, maxRows: e.props.maxRows, viewport: e.viewport, surface: e.surface, drawn, problem, root: $.plugin.root, session: sessionTag, at: now })
420      }
421    } else if (layout === 'full' && cols >= 72) {
422      // 터미널: 칸 수를 세어 열을 맞춘다
423      const barWidth = cols >= 120 ? BAR_WIDTH : cols >= 96 ? 8 : 6
424      const isResetShown = cols >= 100
425      const widths = columnsOf(rows, now, cellWidth)
426      const nameW = Math.max(...rows.map(r => cellWidth(r.name))) + 2
427      mine = (
428        <Box flexDirection="column">
429          {rows.map(r => (
430            <Box key={r.name} flexDirection="row">
431              <Text bold color={r.color}>
432                {padCells(r.name, nameW)}
433              </Text>
434              {widths.map((w, c) => {
435                const m = r.meters[c]
436                const reset = isResetShown && m ? resetText(m, now) : ''
437                const restW = barWidth + 1 + 4 + (isResetShown && w.reset ? 1 + w.reset : 0) + 3
438                if (!m) return <Text key={c}>{' '.repeat(w.label + 1 + restW)}</Text>
439                if (m.pct === undefined) {
440                  return (
441                    <Text key={c} dimColor>
442                      {padCells(m.label, w.label + 1) + padCells('—', restW)}
443                    </Text>
444                  )
445                }
446                const [filled, empty] = barParts(m.pct, barWidth)
447                return (
448                  <Text key={c}>
449                    <Text dimColor>{padCells(m.label, w.label + 1)}</Text>
450                    <Text color={colorFor(m.pct)}>{filled}</Text>
451                    <Text dimColor>{empty}</Text>
452                    <Text bold color={colorFor(m.pct)}>
453                      {padCellsStart(pctText(m.pct), 5)}
454                    </Text>
455                    <Text dimColor>{padCells(isResetShown && w.reset ? ' ' + reset : '', isResetShown && w.reset ? 1 + w.reset : 0) + '   '}</Text>
456                  </Text>
457                )
458              })}
459              {r.tail ? (
460                <Text>
461                  <Text dimColor>{r.tail.label} </Text>
462                  <Text bold color={colorFor(r.tail.pct)}>
463                    {pctText(r.tail.pct)}
464                  </Text>
465                  {'  '}
466                </Text>
467              ) : null}
468              {r.note ? <Text dimColor>{r.note}</Text> : null}
469            </Box>
470          ))}
471        </Box>
472      )
473    } else {
474      // 한 줄: "Claude 5시간 3% 주간 77% Fable 100% ctx 19% │ Codex 주간 40%"
475      mine = (
476        <Box flexDirection="row" flexWrap="wrap">
477          {rows.map((r, i) => (
478            <Text key={r.name}>
479              {i > 0 ? <Text dimColor> │ </Text> : null}
480              <Text bold color={r.color}>
481                {r.name}
482              </Text>
483              {r.meters
484                .filter((m): m is Meter & { pct: number } => m?.pct !== undefined)
485                .map(m => (
486                  <Text key={m.label}>
487                    <Text dimColor> {m.label} </Text>
488                    <Text bold color={colorFor(m.pct)}>
489                      {pctText(m.pct)}
490                    </Text>
491                  </Text>
492                ))}
493              {r.tail ? (
494                <Text>
495                  <Text dimColor> ctx </Text>
496                  <Text bold color={colorFor(r.tail.pct)}>
497                    {pctText(r.tail.pct)}
498                  </Text>
499                </Text>
500              ) : null}
501              {r.meters.every(m => m?.pct === undefined) && r.note ? <Text dimColor> {r.note}</Text> : null}
502            </Text>
503          ))}
504        </Box>
505      )
506    }
507
508    // 다른 mod(예: pocket-pet)가 띠에 그린 것도 함께 보이도록 아래에 붙인다
509    const below = await next(e)
510    return (
511      <Box flexDirection="column" rowGap={0}>
512        {mine}
513        {below}
514      </Box>
515    )
516  })
517}
518
519/** 지금 가진 수치로 Claude 줄과 Codex 줄을 만든다. 열: 5시간 · 주간 · 모델별 주간… */
520function rowsOf(now: number): BandRow[] {
521  const at = (w: { pct: number; resetsAtMs?: number } | undefined, label: string): Meter =>
522    w ? { label, pct: effectivePct({ pct: w.pct, resetsAtMs: w.resetsAtMs }, now) ?? 0, resetsAtMs: w.resetsAtMs } : { label }
523
524  // Claude: 엔진 값과 캐시 중 더 최근 것
525  const fromEngine = (kind: string) => {
526    const l = claude?.limits.find(x => x.kind === kind)
527    if (!l) return undefined
528    const t = l.resetsAt ? Date.parse(l.resetsAt) : NaN
529    return { pct: l.percentUsed, resetsAtMs: Number.isFinite(t) ? t : undefined }
530  }
531  // 같은 순간에 받았으면 사용량 API 쪽(모델별 한도까지 한 벌)을 쓴다
532  const isCacheNewer = claudeCache !== undefined && (!claude || claudeCache.at >= claude.at)
533  const five = (isCacheNewer ? claudeCache?.fiveHour : undefined) ?? fromEngine('five_hour') ?? claudeCache?.fiveHour
534  const week = (isCacheNewer ? claudeCache?.sevenDay : undefined) ?? fromEngine('seven_day') ?? claudeCache?.sevenDay
535  const scoped = (claudeCache?.scoped ?? []).map(s => at(s.window, s.name)) // 모델별 주간 한도: 이름만(Fable)
536  const extra = (claude?.limits ?? [])
537    .filter(l => l.kind !== 'five_hour' && l.kind !== 'seven_day' && l.percentUsed >= 50)
538    .map(l => at({ pct: l.percentUsed, resetsAtMs: l.resetsAt ? Date.parse(l.resetsAt) || undefined : undefined }, CLAUDE_LABEL[l.kind] ?? l.kind))
539
540  const lastSeen = Math.max(claude?.at ?? 0, claudeCache?.at ?? 0)
541  const claudeNote =
542    !five && !week ? '첫 응답 뒤에 한도가 보여요' : (isClaudeFromStore && !isCacheNewer) || now - lastSeen > STALE_MS ? `${agoText(now - lastSeen)} 기록` : undefined
543  // 엔진 값은 새것인데 모델별 한도(API를 못 써서 파일이나 옛 기록에서 온 것)만 오래된 경우: 왜 못 받는지도 붙인다
544  const why =
545    lastFetch?.outcome === 'http' ? ` · API ${lastFetch.status}` : lastFetch?.outcome === 'no-auth' ? ' · 자격 증명 없음' : lastFetch?.outcome === 'error' ? ' · API 연결 실패' : ''
546  const cacheNote =
547    claudeCache && scoped.length > 0 && now - claudeCache.at > STALE_MS
548      ? `${claudeCache.scoped.map(s => s.name).join('·')} ${agoText(now - claudeCache.at)} 기록${why}`
549      : undefined
550  const claudeRow: BandRow = {
551    name: 'Claude',
552    color: CLAUDE_COLOR,
553    meters: five || week ? [at(five, '5시간'), at(week, '주간'), ...scoped, ...extra] : [],
554    tail: contextPct !== undefined ? { label: '컨텍스트', pct: contextPct } : undefined,
555    note: claudeNote ?? cacheNote,
556  }
557
558  const codexRow: BandRow = {
559    name: 'Codex',
560    color: CODEX_COLOR,
561    // 없는 창(요즘 Codex는 5시간 창이 없다)은 빈칸으로 두어 주간끼리 위아래로 맞춘다
562    meters: codex?.short || codex?.week ? [codex.short ? at(codex.short, '5시간') : undefined, codex.week ? at(codex.week, '주간') : undefined] : [],
563    // 앱 서버에서 방금 받은 값에는 "몇 분 전 기록"을 붙이지 않는다(15분 넘게 못 받았으면 붙인다)
564    note: !codex ? '이 PC에 Codex 사용 기록이 없어요' : codex.source === 'live' && now - codex.at < STALE_MS ? undefined : codex.at ? `${agoText(now - codex.at)} 기록` : undefined,
565  }
566  return [claudeRow, codexRow]
567}
568
hooks/claude-cache.ts 66 lines
1// Claude 사용량 API 응답 해석: Claude Code의 /usage 가 받는 것과 같은 응답(api.anthropic.com/api/oauth/usage)을
2// mod가 세션의 자격 증명 핸들($.session.authorize)로 직접 받거나, 그게 안 될 때는 상태줄 스크립트
3// (awesome-statusline)가 같은 응답을 저장해 둔 파일(.claude_usage_cache)에서 읽는다. 토큰은 mod에 오지 않는다.
4//
5//   { "five_hour": { "utilization": 3.0, "resets_at": "…" }, "seven_day": { … },
6//     "limits": [ { "kind": "weekly_scoped", "percent": 100, "resets_at": "…",
7//                   "scope": { "model": { "display_name": "Fable" } } }, … ] }
8//
9// 엔진이 응답마다 주는 한도(five_hour, seven_day)에는 모델별 주간 한도가 없어서,
10// Fable 같은 모델별 한도는 여기서만 얻는다.
11
12export type CachedWindow = {
13  /** 사용한 비율, 0–100 */
14  pct: number
15  /** 리셋 시각(ms, epoch). 모르면 없음 */
16  resetsAtMs?: number
17}
18
19export type ClaudeCache = {
20  /** 받은 시각(ms): API면 받은 때, 파일이면 파일이 마지막으로 바뀐 때 */
21  at: number
22  /** 어디서 왔는지: 사용량 API 직접(api) · 상태줄 캐시 파일(file). 없으면 옛 기록 */
23  source?: 'api' | 'file'
24  fiveHour?: CachedWindow
25  sevenDay?: CachedWindow
26  /** 모델별 주간 한도: 이름(예: Fable)과 창 */
27  scoped: { name: string; window: CachedWindow }[]
28}
29
30const num = (v: unknown): number | undefined => (typeof v === 'number' && Number.isFinite(v) ? v : undefined)
31
32const time = (v: unknown): number | undefined => {
33  if (typeof v !== 'string') return undefined
34  const t = Date.parse(v)
35  return Number.isFinite(t) ? t : undefined
36}
37
38function windowOf(raw: unknown, key: 'utilization' | 'percent'): CachedWindow | undefined {
39  if (!raw || typeof raw !== 'object') return undefined
40  const r = raw as Record<string, unknown>
41  const pct = num(r[key])
42  return pct === undefined ? undefined : { pct, resetsAtMs: time(r.resets_at) }
43}
44
45/** 캐시 파일 내용 → 한도. 모양이 다르면 undefined */
46export function parseClaudeCache(text: string, at: number): ClaudeCache | undefined {
47  let o: Record<string, unknown>
48  try {
49    o = JSON.parse(text) as Record<string, unknown>
50  } catch {
51    return undefined
52  }
53  if (!o || typeof o !== 'object') return undefined
54  const cache: ClaudeCache = { at, fiveHour: windowOf(o.five_hour, 'utilization'), sevenDay: windowOf(o.seven_day, 'utilization'), scoped: [] }
55  for (const l of Array.isArray(o.limits) ? o.limits : []) {
56    if (!l || typeof l !== 'object') continue
57    const limit = l as Record<string, unknown>
58    if (limit.kind !== 'weekly_scoped') continue
59    const scope = (limit.scope ?? {}) as Record<string, Record<string, unknown> | null>
60    const name = scope.model?.display_name ?? scope.surface?.display_name
61    const w = windowOf(limit, 'percent')
62    if (typeof name === 'string' && name && w && !cache.scoped.some(s => s.name === name)) cache.scoped.push({ name, window: w })
63  }
64  return cache.fiveHour || cache.sevenDay || cache.scoped.length > 0 ? cache : undefined
65}
66
hooks/codex.ts 134 lines
1// Codex 사용량 읽기: Codex CLI·앱이 남기는 세션 기록(rollout-*.jsonl)의
2// token_count 이벤트에 들어 있는 rate_limits 스냅숏을 찾아 해석한다.
3//
4//   ~/.codex/sessions/YYYY/MM/DD/rollout-....jsonl
5//   {"timestamp":"…","type":"event_msg","payload":{"type":"token_count",
6//     "info":{…},"rate_limits":{"primary":{"used_percent":12.0,
7//     "window_minutes":300,"resets_at":1790713159},"secondary":{…}}}}
8//
9// 버전마다 모양이 조금씩 달라서(resets_in_seconds ↔ resets_at, primary가
10// 주간인 경우, rate_limits가 null인 줄) 모두 너그럽게 받아들인다.
11
12export type Window = {
13  /** 사용한 비율, 0–100 */
14  pct: number
15  /** 창 길이(분). 300 ≈ 5시간, 10080 = 7일 */
16  windowMin?: number
17  /** 리셋 시각(ms, epoch). 모르면 없음 */
18  resetsAtMs?: number
19}
20
21export type CodexSnapshot = {
22  /** 이 스냅숏이 기록된 시각(ms) */
23  at: number
24  short?: Window
25  week?: Window
26  plan?: string
27  /** 어디서 왔는지: 앱 서버에서 방금 받음(live) · 세션 기록에서 읽음(log). 없으면 옛 기록 */
28  source?: 'live' | 'log'
29}
30
31/** 앱 서버(`account/rateLimits/read`)의 답 → 스냅숏. 창 이름이 camelCase이고 resetsAt이 초 단위다 */
32export function snapshotFromAppServer(result: unknown, at: number): CodexSnapshot | undefined {
33  if (!result || typeof result !== 'object') return undefined
34  const rl = (result as { rateLimits?: unknown }).rateLimits
35  if (!rl || typeof rl !== 'object') return undefined
36  const r = rl as { primary?: unknown; secondary?: unknown; planType?: unknown }
37  const win = (raw: unknown): Window | undefined => {
38    if (!raw || typeof raw !== 'object') return undefined
39    const w = raw as { usedPercent?: unknown; windowDurationMins?: unknown; resetsAt?: unknown }
40    const pct = num(w.usedPercent)
41    if (pct === undefined) return undefined
42    const resets = num(w.resetsAt)
43    return { pct, windowMin: num(w.windowDurationMins), resetsAtMs: resets !== undefined && resets > 0 ? (resets < 1e12 ? resets * 1000 : resets) : undefined }
44  }
45  const wins = [win(r.primary), win(r.secondary)]
46  if (!wins[0] && !wins[1]) return undefined
47  const snap: CodexSnapshot = { at, source: 'live' }
48  wins.forEach((w, i) => {
49    if (!w) return
50    const isShort = w.windowMin !== undefined ? w.windowMin <= 1440 : i === 0
51    if (isShort) snap.short ??= w
52    else snap.week ??= w
53  })
54  if (typeof r.planType === 'string') snap.plan = r.planType
55  return snap
56}
57
58type RawWindow = {
59  used_percent?: unknown
60  window_minutes?: unknown
61  resets_at?: unknown
62  resets_in_seconds?: unknown
63}
64
65const num = (v: unknown): number | undefined =>
66  typeof v === 'number' && Number.isFinite(v) ? v : typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v)) ? Number(v) : undefined
67
68function toWindow(raw: unknown, lineAt: number): Window | undefined {
69  if (!raw || typeof raw !== 'object') return undefined
70  const r = raw as RawWindow
71  const pct = num(r.used_percent)
72  if (pct === undefined) return undefined
73  const windowMin = num(r.window_minutes)
74  let resetsAtMs: number | undefined
75  const at = num(r.resets_at)
76  if (at !== undefined && at > 0) {
77    resetsAtMs = at < 1e12 ? at * 1000 : at
78  } else if (typeof r.resets_at === 'string' && r.resets_at && !Number.isFinite(Number(r.resets_at))) {
79    const t = Date.parse(r.resets_at)
80    if (Number.isFinite(t)) resetsAtMs = t
81  } else {
82    const inSec = num(r.resets_in_seconds)
83    if (inSec !== undefined && lineAt > 0) resetsAtMs = lineAt + inSec * 1000
84  }
85  return { pct, windowMin, resetsAtMs }
86}
87
88/** 한 줄(JSON)에서 스냅숏을 꺼낸다. rate_limits가 없거나 비었으면 undefined */
89export function parseLine(line: string): CodexSnapshot | undefined {
90  if (!line.includes('rate_limits')) return undefined
91  let o: Record<string, unknown>
92  try {
93    o = JSON.parse(line) as Record<string, unknown>
94  } catch {
95    return undefined
96  }
97  const payload = (o.payload ?? o.msg ?? {}) as Record<string, unknown>
98  const rl = (payload.rate_limits ?? o.rate_limits) as Record<string, unknown> | null | undefined
99  if (!rl || typeof rl !== 'object') return undefined
100  const ts = typeof o.timestamp === 'string' ? Date.parse(o.timestamp) : NaN
101  const lineAt = Number.isFinite(ts) ? ts : 0
102  const wins = [toWindow(rl.primary, lineAt), toWindow(rl.secondary, lineAt)]
103  if (!wins[0] && !wins[1]) return undefined
104
105  const snap: CodexSnapshot = { at: lineAt }
106  wins.forEach((w, i) => {
107    if (!w) return
108    // 창 길이로 분류한다(primary가 주간인 버전이 있음). 길이를 모르면 primary=5시간
109    const isShort = w.windowMin !== undefined ? w.windowMin <= 1440 : i === 0
110    if (isShort) snap.short ??= w
111    else snap.week ??= w
112  })
113  const plan = rl.plan_type
114  if (typeof plan === 'string') snap.plan = plan
115  return snap
116}
117
118/** 파일 내용에서 가장 마지막(최신) 스냅숏 */
119export function lastSnapshot(text: string): CodexSnapshot | undefined {
120  const lines = text.split('\n')
121  for (let i = lines.length - 1; i >= 0; i--) {
122    const s = parseLine(lines[i] ?? '')
123    if (s) return s
124  }
125  return undefined
126}
127
128/** 리셋 시각이 지났으면 그 창은 0%로 본다 */
129export function effectivePct(w: Window | undefined, now: number): number | undefined {
130  if (!w) return undefined
131  if (w.resetsAtMs !== undefined && now >= w.resetsAtMs) return 0
132  return w.pct
133}
134
hooks/format.ts 97 lines
1// 막대·색·남은 시간 표시와 띠의 행 모양. 시간대 데이터에 기대지 않도록 "몇 시간 후"로 쓴다.
2
3/** 막대 한 칸(눈금 하나): 사용량 표시에 쓰는 한 창 */
4export type Meter = {
5  label: string
6  /** 사용한 비율, 0–100. 없으면 이 창은 "—"로 그린다 */
7  pct?: number
8  resetsAtMs?: number
9}
10
11/** 띠의 한 줄: Claude 또는 Codex */
12export type BandRow = {
13  name: string
14  /** 이름 색(#rrggbb) */
15  color: string
16  /** 열마다 한 칸. undefined는 빈칸(다른 줄만 그 열이 있을 때) */
17  meters: (Meter | undefined)[]
18  /** 줄 끝: 컨텍스트 같은 값 하나와 흐린 메모 */
19  tail?: { label: string; pct: number }
20  note?: string
21}
22
23export const BAR_WIDTH = 10
24
25/** 50% 미만 초록, 80% 미만 주황, 그 이상 빨강. 밝은·어두운 테마 모두에서 읽히는 중간 밝기 */
26export const hexFor = (pct: number): string => (pct < 50 ? '#2f9e44' : pct < 80 ? '#e8890c' : '#e5484d')
27
28/** 터미널 테마 키 */
29export const colorFor = (pct: number): string => (pct < 50 ? 'success' : pct < 80 ? 'warning' : 'error')
30
31export const pctText = (pct: number): string => `${Math.round(pct)}%`
32
33const EIGHTHS = ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉']
34
35/** 1/8칸까지 나누는 막대: [채운 부분, 빈 부분] */
36export function barParts(pct: number, width = BAR_WIDTH): [string, string] {
37  const eighths = Math.round((Math.max(0, Math.min(100, pct)) / 100) * width * 8)
38  const full = Math.floor(eighths / 8)
39  const part = EIGHTHS[eighths % 8] ?? ''
40  const filled = '█'.repeat(full) + part
41  return [filled, '░'.repeat(width - full - (part ? 1 : 0))]
42}
43
44/** 예전 모양(채움+빈칸을 한 문자열로) */
45export const bar = (pct: number, width = BAR_WIDTH): string => barParts(pct, width).join('')
46
47/** 남은 시간: "3일 4시간", "2시간 13분", "45분", "곧" */
48export function untilText(ms: number): string {
49  if (ms <= 60_000) return '곧'
50  const totalMin = Math.floor(ms / 60_000)
51  const d = Math.floor(totalMin / 1440)
52  const h = Math.floor((totalMin % 1440) / 60)
53  const m = totalMin % 60
54  if (d > 0) return h > 0 ? `${d}일 ${h}시간` : `${d}일`
55  if (h > 0) return m > 0 ? `${h}시간 ${m}분` : `${h}시간`
56  return `${m}분`
57}
58
59/** 지난 시간: "방금", "3분 전", "2시간 전", "1일 전" */
60export function agoText(ms: number): string {
61  if (ms < 60_000) return '방금'
62  const min = Math.floor(ms / 60_000)
63  if (min < 60) return `${min}분 전`
64  const h = Math.floor(min / 60)
65  if (h < 24) return `${h}시간 전`
66  return `${Math.floor(h / 24)}일 전`
67}
68
69/** 한도가 다시 차는 때까지: "1일 13시간 후" */
70export const resetText = (m: Meter, now: number): string =>
71  m.pct !== undefined && m.resetsAtMs !== undefined && m.resetsAtMs > now ? `${untilText(m.resetsAtMs - now)} 후` : ''
72
73/** 터미널에서 차지하는 칸 수(한글·전각은 2칸) */
74export function cellWidth(s: string): number {
75  let w = 0
76  for (const ch of s) {
77    const c = ch.codePointAt(0) ?? 0
78    w += (c >= 0x1100 && c <= 0x115f) || (c >= 0x2e80 && c <= 0xa4cf) || (c >= 0xac00 && c <= 0xd7a3) || (c >= 0xf900 && c <= 0xfaff) || (c >= 0xfe30 && c <= 0xfe4f) || (c >= 0xff00 && c <= 0xff60) ? 2 : 1
79  }
80  return w
81}
82
83export const padCells = (s: string, width: number): string => s + ' '.repeat(Math.max(0, width - cellWidth(s)))
84export const padCellsStart = (s: string, width: number): string => ' '.repeat(Math.max(0, width - cellWidth(s))) + s
85
86/** 열마다 가장 긴 이름표·리셋 글자 너비(칸) */
87export function columnsOf(rows: BandRow[], now: number, measure: (s: string) => number) {
88  const n = Math.max(0, ...rows.map(r => r.meters.length))
89  return Array.from({ length: n }, (_, c) => {
90    const ms = rows.map(r => r.meters[c]).filter((m): m is Meter => m !== undefined)
91    return {
92      label: Math.max(0, ...ms.map(m => measure(m.label))),
93      reset: Math.max(0, ...ms.map(m => measure(resetText(m, now)))),
94    }
95  })
96}
97
hooks/panel.ts 189 lines
1// 데스크톱 앱용 사용량 패널: 회색 띠 안에 지표마다 타일을 놓은 SVG 한 장(도트 타일).
2//
3//   Claude    ┌[5시간]   3시간 5분 후┐ ┌[주간]  1일 13시간 후┐ ┌[Fable] 1일 13시간 후┐
4//   ctx 19%   └3% ■□□┆□□□  -35 여유┘ └77% ■■■■■┆□  적당 ┘ └100% ■■■■■┆■ +22 빠름┘
5//   Codex     ┌[주간]   4일 6시간 후┐
6//   39분 전   └40% ■■□┆□□□□□  적당 ┘
7//
8// 클로 펫 카드처럼 도트 느낌으로 그린다: Neo둥근모 글꼴, 계단 모서리, 2px 테두리와 그림자, 칸 나뉜 막대.
9// 색으로 세 가지를 나눈다.
10//   · 누구 한도인지: 타일 바탕·테두리(Claude 살구색, Codex 코발트색)
11//   · 어느 창인지: 이름표(5시간 주황, 주간 갈색, 모델별 주간 보라, Codex 파랑)
12//   · 얼마나 썼는지: 퍼센트·막대(낮음 초록, 중간 주황, 높음 빨강). 높음이면 타일 테두리도 빨강
13// 막대의 I자 눈금은 "지금까지 흐른 시간"이고(5시간 창은 5시간, 주간·모델별 주간은 7일 기준), 쓴 양이 그보다
14// 5 넘게 앞서면 "빠름", 5 넘게 뒤지면 "여유"다. 글자 크기는 두 가지(작은 글자, 큰 숫자·이름)만 쓴다.
15// 데스크톱 앱의 회색 띠는 화면 배율 200%에서 안쪽이 약 745px이라 그 너비에 맞춘다.
16
17import { pctText, untilText, type BandRow, type Meter } from './format'
18import { NEODGM_WOFF2 } from './neodgm-font'
19
20const FONT = `'NeoDunggeunmo','Malgun Gothic','Apple SD Gothic Neo',monospace`
21const SMALL = 12 // 이름표·남은 시간·페이스·이름 밑 글자
22const BIG = 16 // 퍼센트·이름(도트 글꼴의 원래 크기라 또렷하다)
23const TILE_H = 42
24const TILE_GAP = 6
25const ROW_GAP = 5
26const PX = 2 // 도트 한 칸
27const BAR_H = 6
28const SEG_W = 5 // 막대 한 칸
29const SEG_GAP = 2
30const PAD = 9
31const COLS = 3
32export const WIDTH = 740
33
34/** 누구 한도인지: 타일 클래스(바탕·테두리·그림자 색은 CSS에서 테마별로) */
35const PROVIDER: Record<string, { cls: string; color: string }> = {
36  Claude: { cls: 'c', color: '#d97757' },
37  Codex: { cls: 'x', color: '#3b6fe0' },
38}
39/** 어느 창인지: 이름표 색 */
40function badgeColor(provider: string, label: string): string {
41  if (provider === 'Codex') return label === '5시간' ? '#4f86f7' : '#2a4fbf'
42  if (label === '5시간') return '#e2772e'
43  if (label === '주간') return '#a8502c'
44  return '#7c4dff' // 모델별 주간(Fable 등)
45}
46/** 얼마나 썼는지: 낮음 · 중간 · 높음 */
47const levelColor = (pct: number) => (pct < 50 ? '#1f9d55' : pct < 80 ? '#e8890c' : '#e5484d')
48
49const HOUR = 3_600_000
50const windowOf = (m: Meter) => (m.label === '5시간' ? 5 * HOUR : 7 * 24 * HOUR)
51
52/** 글자 너비(px): Neo둥근모는 한글·기호 1em, 영문·숫자·공백 0.5em */
53export function textWidth(s: string, size = SMALL): number {
54  let w = 0
55  for (const ch of s) w += (ch.codePointAt(0) ?? 0) < 0x80 ? 0.5 : 1
56  return Math.ceil(w * size)
57}
58
59const esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
60
61/** 계단 모서리 사각형: 네 모서리를 도트 steps칸씩 깎는다 */
62function pixelRect(x: number, y: number, w: number, h: number, steps: number): string {
63  const s = steps
64  const p: string[] = [`M${x + s * PX},${y}H${x + w - s * PX}`]
65  for (let i = 1; i <= s; i++) p.push(`V${y + i * PX}H${x + w - (s - i) * PX}`)
66  p.push(`V${y + h - s * PX}`)
67  for (let i = 1; i <= s; i++) p.push(`H${x + w - i * PX}V${y + h - (s - i) * PX}`)
68  p.push(`H${x + s * PX}`)
69  for (let i = 1; i <= s; i++) p.push(`V${y + h - i * PX}H${x + (s - i) * PX}`)
70  p.push(`V${y + s * PX}`)
71  for (let i = 1; i <= s; i++) p.push(`H${x + i * PX}V${y + (s - i) * PX}`)
72  return p.join('') + 'Z'
73}
74
75/** 지금까지 흐른 시간(창 길이에 대한 %). 리셋 시각을 모르면 undefined */
76export function elapsedPct(m: Meter, now: number): number | undefined {
77  if (m.resetsAtMs === undefined || m.resetsAtMs <= now) return undefined
78  return Math.max(0, Math.min(100, (1 - (m.resetsAtMs - now) / windowOf(m)) * 100))
79}
80
81/** 페이스: 쓴 양 - 흐른 시간. 5 넘게 앞서면 빠름, 5 넘게 뒤지면 여유 */
82export function paceOf(m: Meter, now: number): { delta: number; text: string; color: string } | undefined {
83  const e = elapsedPct(m, now)
84  if (m.pct === undefined || e === undefined) return undefined
85  const delta = Math.round(m.pct - e)
86  if (delta > 5) return { delta, text: `+${delta} 빠름`, color: '#e5484d' }
87  if (delta < -5) return { delta, text: `${delta} 여유`, color: '#1f9d55' }
88  return { delta, text: '적당', color: '#a08a7a' }
89}
90
91export function panelSvg(rows: BandRow[], now: number, width = WIDTH): { svg: string; width: number; height: number } {
92  // 이름 밑 작은 글자: 메모(옛 기록·못 받는 까닭)가 있으면 그것을, 없으면 컨텍스트. 메모는 뭔가 어긋났을 때만 생기므로
93  // 그때는 컨텍스트보다 먼저 보여야 한다
94  const noteOf = (r: BandRow) => (r.note ?? '').replace(/ 기록(?= ·|$)/, '')
95  const subOf = (r: BandRow) => (r.note ? noteOf(r) : r.tail ? `ctx ${pctText(r.tail.pct)}` : '')
96  const nameW = Math.max(...rows.map(r => Math.max(textWidth(r.name, BIG), textWidth(subOf(r))))) + 14
97  const tileW = Math.floor((width - nameW - TILE_GAP * (COLS - 1)) / COLS)
98
99  const parts: string[] = []
100  let y = 0
101  rows.forEach(r => {
102    const text = (tx: number, ty: number, s: string, cls: string, extra = '') =>
103      parts.push(`<text x="${tx}" y="${ty}"${cls ? ` class="${cls}"` : ''}${extra}>${esc(s)}</text>`)
104    const prov = PROVIDER[r.name] ?? { cls: 'c', color: r.color }
105    // 이름과 그 밑 작은 글자(메모가 있으면 메모, 아니면 컨텍스트)
106    text(0, y + 13, r.name, 'b', ` fill="${prov.color}"`)
107    if (r.note) {
108      text(0, y + 30, noteOf(r), 'mut')
109    } else if (r.tail) {
110      text(0, y + 30, 'ctx', 'mut')
111      text(textWidth('ctx '), y + 30, pctText(r.tail.pct), '', ` fill="${levelColor(r.tail.pct)}"`)
112    }
113
114    const meters = r.meters.filter((m): m is Meter => m !== undefined).slice(0, COLS)
115    meters.forEach((m, i) => {
116      const x = nameW + i * (tileW + TILE_GAP)
117      const edge = m.pct !== undefined && m.pct >= 80 ? 'h' : prov.cls
118      // 타일: 그림자 → 테두리 → 바탕(2px 안쪽) 순으로 겹쳐 도트 테두리를 만든다
119      const w = tileW - PX
120      const h = TILE_H - PX
121      parts.push(`<path class="${edge}s" d="${pixelRect(x + PX, y + PX, w, h, 2)}"/>`)
122      parts.push(`<path class="${edge}l" d="${pixelRect(x, y, w, h, 2)}"/>`)
123      parts.push(`<path class="${prov.cls}f" d="${pixelRect(x + PX, y + PX, w - 2 * PX, h - 2 * PX, 1)}"/>`)
124      const x0 = x + PAD
125      const x1 = x + w - PAD
126      // 윗줄: 어느 창인지 이름표 · 남은 시간
127      const bw = textWidth(m.label) + 10
128      parts.push(`<path d="${pixelRect(x0 - 2, y + 5, bw, 14, 1)}" fill="${badgeColor(r.name, m.label)}"/>`)
129      text(x0 + 3, y + 12, m.label, 'w')
130      if (m.pct !== undefined && m.resetsAtMs !== undefined && m.resetsAtMs > now) {
131        text(x1, y + 12, `${untilText(m.resetsAtMs - now)} 후`, 'mut', ' text-anchor="end"')
132      }
133      // 아랫줄: 퍼센트 · 칸 막대(흐른 시간 눈금) · 페이스
134      const ry = y + 30
135      if (m.pct === undefined) {
136        text(x0, ry, '—', 'mut b')
137        return
138      }
139      const color = levelColor(m.pct)
140      // 퍼센트는 윗줄 이름표와 같은 자리에서 시작하고, 막대가 남은 폭을 채운다
141      const pct = pctText(m.pct)
142      text(x0 - 2, ry, pct, 'b', ` fill="${color}"`)
143      const pace = paceOf(m, now)
144      const paceW = pace ? textWidth(pace.text) + 8 : 0
145      const bx0 = x0 - 2 + textWidth(pct, BIG) + 6
146      const avail = Math.max(20, x1 - paceW - bx0)
147      const n = Math.max(4, Math.floor((avail + SEG_GAP) / (SEG_W + SEG_GAP)))
148      const barW = n * (SEG_W + SEG_GAP) - SEG_GAP
149      const lit = m.pct <= 0 ? 0 : Math.max(1, Math.round((Math.min(100, m.pct) / 100) * n))
150      const by = ry - BAR_H / 2
151      for (let k = 0; k < n; k++) {
152        const sx = bx0 + k * (SEG_W + SEG_GAP)
153        parts.push(
154          k < lit
155            ? `<rect x="${sx}" y="${by}" width="${SEG_W}" height="${BAR_H}" fill="${color}"/>`
156            : `<rect class="trk" x="${sx}" y="${by}" width="${SEG_W}" height="${BAR_H}"/>`,
157        )
158      }
159      const e = elapsedPct(m, now)
160      if (e !== undefined) {
161        // 흐른 시간: 위아래에 가로선이 있는 대문자 I 모양 눈금
162        const tx = Math.round((bx0 + (e / 100) * barW) / PX) * PX - PX / 2
163        parts.push(`<rect class="tick" x="${tx}" y="${by - 4}" width="${PX}" height="${BAR_H + 8}"/>`)
164        parts.push(`<rect class="tick" x="${tx - PX}" y="${by - 4}" width="${PX * 3}" height="${PX}"/>`)
165        parts.push(`<rect class="tick" x="${tx - PX}" y="${by + BAR_H + 2}" width="${PX * 3}" height="${PX}"/>`)
166      }
167      if (pace) text(x1, ry, pace.text, '', ` text-anchor="end" fill="${pace.color}"`)
168    })
169    y += TILE_H + ROW_GAP
170  })
171  const height = Math.max(TILE_H, y - ROW_GAP)
172  const total = Math.ceil(nameW + COLS * tileW + TILE_GAP * (COLS - 1))
173
174  const style =
175    `@font-face{font-family:'NeoDunggeunmo';src:url(data:font/woff2;base64,${NEODGM_WOFF2}) format('woff2')}` +
176    `svg{shape-rendering:crispEdges}` +
177    `text{font-family:${FONT};font-size:${SMALL}px;dominant-baseline:central}` +
178    `.b{font-size:${BIG}px}.w{fill:#ffffff}.mut{fill:#8a6a58}` +
179    `.cf{fill:#fff6ef}.cl{fill:#d97757}.cs{fill:#ecc3ae}` +
180    `.xf{fill:#eff4ff}.xl{fill:#3b6fe0}.xs{fill:#b9cbf5}` +
181    `.hl{fill:#e5484d}.hs{fill:#f2b0b2}` +
182    `.trk{fill:#8a6a58;fill-opacity:.2}.tick{fill:#4a3529}` +
183    `@media (prefers-color-scheme:dark){.mut{fill:#cdb6a6}` +
184    `.cf{fill:#3a2a23}.cs{fill:#1c1310}.xf{fill:#1f2740}.xl{fill:#6b93ff}.xs{fill:#0f1528}.hs{fill:#2a1213}` +
185    `.trk{fill:#f2e6dc;fill-opacity:.22}.tick{fill:#fff2e6}}`
186  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${total}" height="${height}" viewBox="0 0 ${total} ${height}"><style>${style}</style>${parts.join('')}</svg>`
187  return { svg, width: total, height }
188}
189
hooks/neodgm-font.ts 4 lines
1// Neo둥근모(NeoDunggeunmo) v1.601 woff2, SIL OFL 1.1 — fonts/LICENSE-neodgm.txt
2// 사용량 패널 SVG가 그림으로 그려지므로 글꼴을 data URI로 넣는다.
3export const NEODGM_WOFF2 = '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MzOr841zzjnnnHPOOeecc84555xzrmdmZmZmZmZmZmZmZmZmPTMzMzMzMzMzMzMzMzPrmZmZmZmZmZmZmZmZmVnHOeecc84555xzzjnnnHPOOdd1zjnnnHPOOeecc84555xzzvXNzMzMzMzMzMzMzMzMrG9mZmZmZmZmZmZmZmZmfTMzMzMzMzMzMzMzMzPrOuecc84555xzzjnnnHPOOec6zjnnnHPOOeecc84555xzzrmemZmZmZmZmZmZmZmZmTWsmZmZmZmZmZmZmZmZmfWgXjMzMzMzMzMzMzMzMzNrMzMzMzMzMzMzMzMzM2szMzMzMzMzMzMzMzMzazMzMzMzMzMzMzMzMzNrMzMzMzMzMzMzMzMzM2szMzMzMzMzMzMzMzMzazMzMzMzMzMzMzMzMzNrMzMzMzMzMzMzMzMzM6vzjXPOOeecc84555xzzjnnnHOuZ2ZmZmZmZmZmZmZmZmY9MzMzMzMzMzMzMzMzM+uZmZmZmZmZmZmZmZmZWcc555xzzjnnnHPOOeecc84513XOOeecc84555xzzjnnnHPO9c3MzMzMzMzMzMzMzMysb2ZmZmZmZmZmZmZmZmZ9MzMzMzMzMzMzMzMzM+s655xzzjnnnHPOOeecc8455zrOOeecc84555xzzjnnnHPOuZ6ZmZmZmZmZmZmZmZmZNayZmZmZmZmZmZmZmZmZdVyvmZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZFcvMzMzMzMzMzMzMzMzMypOZmZmZmZmZmZmZmZmZNTMzMzMzMzMzMzMzMzNrZmZmZmZmZmZmZmZmZtboMjMzMzMzMzMzMzMzM7POzMzMzMzMzMzMzMzMzMqzmZmZmZmZmZmZmZmZmXUzMzMzMzMzMzMzMzMz62ZmZmZmZmZmZmZmZmbW6GZmZmZmZmZmZmZmZmZmzczMzMzMzMzMzMzMzMyKZWZmZmZmZmZmZmZmZmYds2ZmZmZmZmZmZmZmZmbWw946MzMzMzMzMzMzMzMzM+uZmZmZmZmZmZmZmZmZWc/MzMzMzMzMzMzMzMzMemZmZmZmZmZmZmZmZmbWMzMzMzMzMzMzMzMzM7OemZmZmZmZmZmZmZmZmfXMzMzMzMzMzMzMzMzMrGdmZmZmZmZmZmZmZmZmfTzP8zzP8zzP8zzP8zzP8zzP8zzP6+ecc84555xzzjnnnHPOOeec6+ecc84555xzzjnnnHPOOeec6+ecc84555xzzjnnnHPOOeec6+N5nud5nud5nud5nud5nud5nud5Xl/P8zzP8zzP8zzP8zzP8zzP8zzP8/o755xzzjnnnHPOOeecc8455/o755xzzjnnnHPOOeecc8455/o755xzzjnnnHPOOeecc8455/p6nud5nud5nud5nud5nud5nud5ntfH8zzP8zzP8zzP8zzP8zzP8zzP87x+zjnnnHPOOeecc84555xzzrmemZmZmZmZmZmZmZmZmVW9zMzMzMzMzMzMzMzMzKyZmZmZmZmZmZmZmZmZWTMzMzMzMzMzMzMzMzOzZmZmZmZmZmZmZmZmZmbNzMzMzMzMzMzMzMzMzJqZmZmZmZmZmZmZmZmZNTMzMzMzMzMzMzMzMzNrZmZmZmZmZmZmZmZmZlYwMzMzMzMzMzMzMzMzM+tde5iZmZmZmZmZmZmZmZn1mZmZmZmZmZmZmZmZmVmfmZmZmZmZmZmZmZmZmfVzZMzMzMzMzMzMzMzMzMw6MzMzMzMzMzMzMzMzM2s8Z2ZmZmZmZmZmZmZmZmY9MzMzMzMzMzMzMzMzM+uZmZmZmZmZmZmZmZmZWSOcmZmZmZmZmZmZmZmZmTUzMzMzMzMzMzMzMzMz6w0xMzMzMzMzMzMzMzMz6xHMzMzMzMzMzMzMzMzMzLon5ZiZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmRXLzMzMzMzMzMzMzMzMzMqTmZmZmZmZmZmZmZmZmTUzMzMzMzMzMzMzMzMza2ZmZmZmZmZmZmZmZmbW6DIzMzMzMzMzMzMzMzOzbmZmZmZmZmZmZmZmZmbl2czMzMzMzMzMzMzMzMy6mZmZmZmZmZmZmZmZmXUzMzMzMzMzMzMzMzMza3SbmZmZmZmZmZmZmZmZWTMzMzMzMzMzMzMzMzOzYpmZmZmZmZmZmZmZmZlZJ6yZmZmZmZmZmZmZmZmZdVqvmZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZFYyZmZmZmZmZmZmZmZmZdWZhZmZmZmZmZmZmZmZm1jAzMzMzMzMzMzMzMzOzhpmZmZmZmZmZmZmZmZk1wpiZmZmZmZmZmZmZmZlZa2ZmZmZmZmZmZmZmZma9WZiZmZmZmZmZmZmZmZl1mpmZmZmZmZmZmZmZmVmnmZmZmZmZmZmZmZmZmTXCmpmZmZmZmZmZmZmZmVljZmZmZmZmZmZmZmZmZp0hZmZmZmZmZmZmZmZmZp2yZmZmZmZmZmZmZmZmZtbjes3MzMzMzMzMzMzMzMyszczMzMzMzMzMzMzMzKzNzMzMzMzMzMzMzMzMrM3MzMzMzMzMzMzMzMyszczMzMzMzMzMzMzMzKzNzMzMzMzMzMzMzMzMrM3MzMzMzMzMzMzMzMyszczMzMzMzMzMzMzMzKzON84555xzzjnnnHPOOeecc865npmZmZmZmZmZmZmZmZn1zMzMzMzMzMzMzMzMzKxnZmZmZmZmZmZmZmZmZh3nnHPOOeecc84555xzzjnnXNc555xzzjnnnHPOOeecc8451zczMzMzMzMzMzMzMzOzvpmZmZmZmZmZmZmZmZn1zczMzMzMzMzMzMzMzKzrnHPOOeecc84555xzzjnnnOs455xzzjnnnHPOOeecc84553pmZmZmZmZmZmZmZmZm1rBmZmZmZmZmZmZmZmZm1pN6mZmZmZmZmZmZmZmZmVkzMzMzMzMzMzMzMzMzs2ZmZmZmZmZmZmZmZmZmzczMzMzMzMzMzMzMzMyamZmZmZmZmZmZmZmZmTUzMzMzMzMzMzMzMzMza2ZmZmZmZmZmZmZmZmbWzMzMzMzMzMzMzMzMzKzON84555xzzjnnnHPOOeecc865npmZmZmZmZmZmZmZmZn1zMzMzMzMzMzMzMzMzKxnZmZmZmZmZmZmZmZmZh3nnHPOOeecc84555xzzjnnXNc555xzzjnnnHPOOeecc8451zczMzMzMzMzMzMzMzOzvpmZmZmZmZmZmZmZmZn1zczMzMzMzMzMzMzMzKzrnHPOOeecc84555xzzjnnnOs455xzzjnnnHPOOeecc84553pmZmZmZmZmZmZmZmZm1rDMzMzMzMzMzMzMzMzMrLN6zczMzMzMzMzMzMzMzKzNzMzMzMzMzMzMzMzMrM3MzMzMzMzMzMzMzMyszczMzMzMzMzMzMzMzKzNzMzMzMzMzMzMzMzMrM3MzMzMzMzMzMzMzMyszczMzMzMzMzMzMzMzKzNzMzMzMzMzMzMzMzMrFjMzMzMzMzMzMzMzMzMrDyZmZmZmZmZmZmZmZmZWTMzMzMzMzMzMzMzMzOzZmZmZmZmZmZmZmZmZmaNLmZmZmZmZmZmZmZmZmbWNjMzMzMzMzMzMzMzM7Py3MzMzMzMzMzMzMzMzMx6MzMzMzMzMzMzMzMzM+vNzMzMzMzMzMzMzMzMrNG1mZmZmZmZmZmZmZmZmTVmZmZmZmZmZmZmZmZmViwzMzMzMzMzMzMzMzMz64w1MzMzMzMzMzMzMzMzs57Wa2ZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZnW+cc4555xzzjnnnHPOOeecc871zMzMzMzMzMzMzMzMzKxnZmZmZmZmZmZmZmZmZj0zMzMzMzMzMzMzMzMz6zjnnHPOOeecc84555xzzjnnus4555xzzjnnnHPOOeecc865vpmZmZmZmZmZmZmZmZn1zczMzMzMzMzMzMzMzKxvZmZmZmZmZmZmZmZmZl3nnHPOOeecc84555xzzjnnXMc555xzzjnnnHPOOeecc8451zMzMzMzMzMzMzMzMzOzhjUzMzMzMzMzMzMzMzOzntVrZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmbWZmZmZmZmZmZmZmZmZtZmZmZmZmZmZmZmZmZm1mZmZmZmZmZmZmZmZmdb5xzjnnnHPOOeecc84555xzzvXMzMzMzMzMzMzMzMzMrGdmZmZmZmZmZmZmZmZmPTMzMzMzMzMzMzMzMzPrOOecc84555xzzjnnnHPOOee6zjnnnHPOOeecc84555xzzrm+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CWVcSKWNdf0hQIQJZVxIpY11/RFAhAllXEiljXX9MUCECWVcSKWNdf0JQIQJZVxIpY11/SlAhAllXEiljXX9GUCECWVcSKWNdf05QIQJZVxIpY11/QVAhAllXEiljXX9JUCECWVcSKWNdf0VQIQJZVxIpY11/TVAhAllXEiljXX9DUCECWVcSKWNdf0tQIQJZVxIpY11/R1AhAllXEiljXX9fYAIE8q4kEob6+6/DwARJpRxIZU21vWHABEmlHEhlTbW9UcAESaUcSGVNtb1xwARJpRxIZU21vUnABEmlHEhlTbW9acAESaUcSGVNtb1ZwARJpRxIZU21vXnABEmlHEhlTbW9RcAESaUcSGVNtb1lwARJpRxIZU21vVXABEmlHEhlTbW9dcAESaUcSGVNtb1NwARJpRxIZU21vW3ABEmlHEhlTbW9XcAESaUcSGVNtb19wEiTCjjQiptrPv+3wAAESaUcSGVNtb1hwARJpRxIZU21vVHABEmlHEhlTbW9ccAESaUcSGVNtb1JwARJpRxIZU21vWnABEmlHEhlTbW9WcAESaUcSGVNtb15wARJpRxIZU21vUXABEmlHEhlTbW9ZcAESaUcSGVNtb1VwARJpRxIZU21vXXABEmlHEhlTbW9TcAESaUcSGVNtb1twARJpRxIZU21vV3ABEmlHEhlTbW9fcBIkwo40Iqbay7/xAAIkwo40IqbazrDwEiTCjjQiptrOuPACJMKONCKm2s648BIkwo40IqbazrTwAiTCjjQiptrOtPASJMKONCKm2s688AIkwo40IqbazrzwEiTCjjQiptrOsvACJMKONCKm2s6y8BIkwo40IqbazrrwAiTCjjQiptrOuvASJMKONCKm2s628AIkwo40IqbazrbwEiTCjjQiptrOvvACJMKONCKm2s6+8DRJhQxoVU2lh3/xEARJhQxoVU2ljXHwJEmFDGhVTaWNcfAUSYUMaFVNpY1x8DRJhQxoVU2ljXnwBEmFDGhVTaWNefAkSYUMaFVNpY158BRJhQxoVU2ljXnwNEmFDGhVTaWNdfAESYUMaFVNpY118CRJhQxoVU2ljXXwFEmFDGhVTaWNdfA0SYUMaFVNpY198ARJhQxoVU2ljX3wJEmFDGhVTaWNffAUSYUMaFVNpY198HiDChjAuptLHu/mMAiDChjAuptLGuPwSIMKGM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'
4