mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 16:09:43 +02:00
feat(usage): plan usage limits header chip via statusLine telemetry
Surface Claude subscription plan usage limits (5-hour rolling + 7-day weekly: percent used + reset time) in the header, opt-in via App Settings → Display → "Plan Usage Limits" (default OFF, no behavior change when off). A Codeman-managed Claude statusLine exporter forwards the rate_limits JSON to a new auth-exempt POST /api/status-telemetry (same loopback + hook-secret gate as /api/hook-event); parsed telemetry broadcasts over SSE session:statusTelemetry to a header chip (amber >=80%, red >=95%, reset times on hover). The exporter prints the same summary back as the in-terminal footer (print-through). - src/usage-telemetry.ts: pure parser/formatter (epoch-sec -> ms, clamp, change signature) + test/usage-telemetry.test.ts - hooks-config.ts: generateStatusLineCommand + applyStatusLineConfig (add/remove; never clobbers a user's own statusLine) - session-routes.ts: inject gate (Claude-only, Codeman-managed cases), driven by create-payload statusLineTelemetry (session-ui.js) - schemas.ts: StatusTelemetrySchema + showPlanUsageLimits + payload field - frontend: header chip, applyHeaderVisibilitySettings toggle, renderIndexHtml strip, _onSessionStatusTelemetry handler Schema empirically confirmed against Claude Code 2.1.177 (Claude Max): only five_hour/seven_day windows exist (no Opus-weekly field); rate_limits is absent before the first API response and for non-subscriber auth. Design + verification method in docs/usage-limits-display-plan.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -158,6 +158,8 @@ export const CreateSessionSchema = z.object({
|
||||
effort: effortLevelSchema,
|
||||
/** Model override to write to .claude/settings.local.json (e.g., "opus[1m]"). Empty string clears. */
|
||||
modelOverride: z.string().max(50).optional(),
|
||||
/** Inject the plan-usage statusLine exporter into the case (App Settings → Display → "Plan Usage Limits"). Claude-only. */
|
||||
statusLineTelemetry: z.boolean().optional(),
|
||||
openCodeConfig: OpenCodeConfigSchema,
|
||||
codexConfig: CodexConfigSchema,
|
||||
/** Resume a previous Claude conversation by its session ID (used for reboot recovery) */
|
||||
@@ -186,6 +188,37 @@ export const ResizeSchema = z.object({
|
||||
viewportType: z.enum(['mobile', 'tablet', 'desktop']).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for POST /api/status-telemetry
|
||||
* Claude Code statusline payload forwarded by the Codeman-managed statusLine
|
||||
* exporter (see hooks-config.generateStatusLineCommand). Validates only the
|
||||
* subset Codeman displays; unknown keys (session_id, transcript_path, cwd, …)
|
||||
* are stripped by z.object. Auth-exempt like /api/hook-event.
|
||||
*/
|
||||
const RateLimitWindowSchema = z
|
||||
.object({
|
||||
used_percentage: z.number().optional(),
|
||||
resets_at: z.number().optional(),
|
||||
})
|
||||
.optional();
|
||||
|
||||
export const StatusTelemetrySchema = z.object({
|
||||
sessionId: z.string().min(1).max(100),
|
||||
data: z
|
||||
.object({
|
||||
rate_limits: z
|
||||
.object({
|
||||
five_hour: RateLimitWindowSchema,
|
||||
seven_day: RateLimitWindowSchema,
|
||||
})
|
||||
.optional(),
|
||||
context_window: z.object({ used_percentage: z.number().optional() }).optional(),
|
||||
cost: z.object({ total_cost_usd: z.number().optional() }).optional(),
|
||||
model: z.object({ display_name: z.string().max(100).optional() }).optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
// ========== Case Routes ==========
|
||||
|
||||
/**
|
||||
@@ -321,6 +354,7 @@ export const SettingsUpdateSchema = z
|
||||
showFileBrowser: z.boolean().optional(),
|
||||
showSubagents: z.boolean().optional(),
|
||||
showMultiMonitorButton: z.boolean().optional(),
|
||||
showPlanUsageLimits: z.boolean().optional(),
|
||||
// Input
|
||||
gestureControlEnabled: z.boolean().optional(),
|
||||
// Claude CLI settings
|
||||
|
||||
Reference in New Issue
Block a user