Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf8821f3f9 |
Vendored
+8
@@ -1,3 +1,11 @@
|
||||
devdesk (0.9.5) bookworm; urgency=medium
|
||||
|
||||
* Context use is shown in tokens as well as percent (#43): Claude's
|
||||
footer shows "ctx 34% 346k/1M", and the Sessions panel and session
|
||||
switcher show "ctx 34% · 346k/1M".
|
||||
|
||||
-- Jared Vititoe <jjvititoe1@gmail.com> Sun, 11 Oct 2026 23:07:00 -0400
|
||||
|
||||
devdesk (0.9.4) bookworm; urgency=medium
|
||||
|
||||
* The inbox badge no longer only grows (#42). Opening the bell marks its
|
||||
|
||||
@@ -43,16 +43,20 @@ if [[ $session =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Footer line: session · model · context % · plan use. ANSI colour numbers, not
|
||||
# Footer line: session · model · context % and tokens · plan use. ANSI colour numbers, not
|
||||
# RGB, so the browser's dark or light palette applies (devdesk#31). Claude sends
|
||||
# rate_limits only to Pro/Max subscribers; there .cost is an API-price estimate,
|
||||
# not a bill, so show the 5-hour plan use instead and keep $ for API-key billing.
|
||||
jq -rM --arg s "$session" '
|
||||
def c($sgr; $t): "\u001b[\($sgr)m\($t)\u001b[0m";
|
||||
def pct: if . == null then "—" else "\(. | floor)%" end;
|
||||
def tok: if . >= 1000000 then "\(. / 100000 | round / 10)M" elif . >= 1000 then "\(. / 1000 | round)k" else "\(.)" end;
|
||||
def ctxtok: .context_window | (.current_usage | if . then (.input_tokens // 0) + (.cache_creation_input_tokens // 0)
|
||||
+ (.cache_read_input_tokens // 0) else null end) as $u
|
||||
| if $u == null then "" else " \($u | tok)\(if .context_window_size then "/\(.context_window_size | tok)" else "" end)" end;
|
||||
[ (if $s != "" then c("33"; "◈ \($s)") else empty end),
|
||||
c("36"; .model.display_name // "Claude"),
|
||||
c("37"; "ctx \(.context_window.used_percentage | pct)"),
|
||||
c("37"; "ctx \(.context_window.used_percentage | pct)\(ctxtok)"),
|
||||
(if .rate_limits.five_hour.used_percentage != null
|
||||
then c("37"; "5h \(.rate_limits.five_hour.used_percentage | pct)")
|
||||
else c("37"; "$\((.cost.total_cost_usd // 0) * 100 | round / 100)") end)
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@ claude_args() {
|
||||
"cost":{"total_cost_usd":1.5,"total_lines_added":10,"total_lines_removed":2}}'
|
||||
run bash -c "echo '$status_json' | TMUX='$DEVDESK_SOCKET,1,0' TMUX_PANE='$pane' '$REPO/libexec/devdesk-statusline'"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ $output == *"alpha"* && $output == *"ctx 34%"* ]]
|
||||
[[ $output == *"alpha"* && $output == *"ctx 34% 346k/1M"* ]]
|
||||
run devdesk attach --list
|
||||
[ "$(jq -r '.sessions[] | select(.name=="alpha") | .context.used_tokens' <<<"$output")" = 346000 ]
|
||||
[ "$(jq -r '.sessions[] | select(.name=="alpha") | .context.model' <<<"$output")" = Opus ]
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import {
|
||||
TtydConnection, fetchAlerts, fetchRepo, fetchToken, investigateAlert, sessionAction, uploadFile, AuthExpiredError, UnauthorizedError,
|
||||
} from './connection.js';
|
||||
import { parseTitle, pasteSafe, sessionFromSearch } from './protocol.js';
|
||||
import { SessionsPanel, recentNames, rememberSession, sessionStatus } from './sessions.js';
|
||||
import { SessionsPanel, ctxLabel, recentNames, rememberSession, sessionStatus } from './sessions.js';
|
||||
import { renderAlerts } from './alerts.js';
|
||||
import { renderRepo } from './repo.js';
|
||||
import { bindAskClaude } from './widgets.js';
|
||||
@@ -547,7 +547,7 @@ function renderSwitcher() {
|
||||
};
|
||||
const items = sessions.map((s) => {
|
||||
const status = sessionStatus(s);
|
||||
const ctx = s.context?.used_pct != null ? ` · ctx ${Math.floor(s.context.used_pct)}%` : '';
|
||||
const ctx = s.context?.used_pct != null ? ` · ${ctxLabel(s.context)}` : '';
|
||||
return el('button', {
|
||||
type: 'button', role: 'menuitem',
|
||||
class: `dd-menu-item dd-switch-item is-${status.key}${s.name === state.session ? ' is-current' : ''}`,
|
||||
|
||||
+9
-1
@@ -46,6 +46,14 @@ function renameRecent(from, to) {
|
||||
writeRecents(readRecents().map((r) => (r.name === from ? { ...r, name: to } : r)));
|
||||
}
|
||||
|
||||
// "ctx 34% · 346k/1M": context use as a share of the window and in tokens.
|
||||
const tokens = (n) => (n >= 1e6 ? `${+(n / 1e6).toFixed(n % 1e6 ? 1 : 0)}M` : n >= 1000 ? `${Math.round(n / 1000)}k` : String(n));
|
||||
export function ctxLabel(c) {
|
||||
if (c?.used_pct == null) return '';
|
||||
const count = c.used_tokens != null ? ` · ${tokens(c.used_tokens)}${c.window ? `/${tokens(c.window)}` : ''}` : '';
|
||||
return `ctx ${Math.floor(c.used_pct)}%${count}`;
|
||||
}
|
||||
|
||||
export function ago(epochSeconds) {
|
||||
if (!epochSeconds) return '';
|
||||
const s = Math.max(0, Date.now() / 1000 - epochSeconds);
|
||||
@@ -267,7 +275,7 @@ export class SessionsPanel {
|
||||
renderSession(s) {
|
||||
const isCurrent = s.name === this.current;
|
||||
const status = sessionStatus(s);
|
||||
const ctx = s.context?.used_pct != null ? `ctx ${Math.floor(s.context.used_pct)}%` : '';
|
||||
const ctx = ctxLabel(s.context);
|
||||
const since = s.status?.since ? ago(s.status.since) : ago(s.activity);
|
||||
const model = isCurrent && s.context?.model ? s.context.model.replace(/^Claude\s+/i, '') : '';
|
||||
const meta = s.running
|
||||
|
||||
Reference in New Issue
Block a user