@ravshansbox/pi-statusline 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -3
  2. package/index.ts +15 -64
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,9 +14,8 @@ Add `-l` to install it in project settings.
14
14
 
15
15
  Pi loads the extension from `./index.ts`. It replaces the built-in footer with a statusline that shows:
16
16
 
17
- - the working directory, git branch and session name
18
- - token usage, cache hit rate, cost and context usage
19
- - the provider, model and thinking level
17
+ - the directory name, git branch, model and thinking level
18
+ - token usage, cache hit rate and context usage
20
19
  - statuses set by other extensions
21
20
 
22
21
  ## Development
package/index.ts CHANGED
@@ -1,13 +1,12 @@
1
- import { isAbsolute, relative, resolve, sep } from 'node:path';
1
+ import { basename } from 'node:path';
2
2
  import { type ExtensionAPI, type ExtensionContext } from '@earendil-works/pi-coding-agent';
3
- import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
3
+ import { truncateToWidth } from '@earendil-works/pi-tui';
4
4
 
5
5
  type Usage = {
6
6
  input: number;
7
7
  output: number;
8
8
  cacheRead: number;
9
9
  cacheWrite: number;
10
- cost: { total: number };
11
10
  };
12
11
 
13
12
  function sanitizeStatusText(text: string): string {
@@ -23,23 +22,14 @@ function formatTokens(count: number): string {
23
22
  return `${Math.round(count / 1000000)}m`;
24
23
  }
25
24
 
26
- function formatCwd(cwd: string, home: string | undefined): string {
27
- if (!home) return cwd;
28
- const rel = relative(resolve(home), resolve(cwd));
29
- const inside = rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
30
- if (!inside) return cwd;
31
- return rel === '' ? '~' : `~${sep}${rel}`;
32
- }
33
-
34
25
  function getUsage(ctx: ExtensionContext) {
35
- const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
26
+ const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
36
27
  let latestCacheHitRate: number | undefined;
37
28
  const add = (u: Usage) => {
38
29
  totals.input += u.input;
39
30
  totals.output += u.output;
40
31
  totals.cacheRead += u.cacheRead;
41
32
  totals.cacheWrite += u.cacheWrite;
42
- totals.cost += u.cost.total;
43
33
  };
44
34
  for (const entry of ctx.sessionManager.getEntries()) {
45
35
  if (entry.type === 'usage') {
@@ -79,14 +69,16 @@ export default function (pi: ExtensionAPI) {
79
69
  const contextPercent =
80
70
  contextUsage?.percent != null ? contextPercentValue.toFixed(0) : '?';
81
71
 
82
- let pwd = formatCwd(
83
- ctx.sessionManager.getCwd(),
84
- process.env['HOME'] || process.env['USERPROFILE'],
85
- );
72
+ const modelName = model?.id.replace(/^claude-/, '') || 'no-model';
73
+ const topParts = [basename(ctx.sessionManager.getCwd())];
86
74
  const branch = footerData.getGitBranch();
87
- if (branch) pwd = `${pwd} (${branch})`;
88
- const sessionName = ctx.sessionManager.getSessionName();
89
- if (sessionName) pwd = `${pwd} • ${sessionName}`;
75
+ if (branch) topParts.push(branch);
76
+ topParts.push(modelName);
77
+ if (model?.reasoning) {
78
+ const level = ctx.thinkingLevel || 'off';
79
+ topParts.push(level === 'off' ? 'thinking off' : level);
80
+ }
81
+ const top = topParts.join(' • ');
90
82
 
91
83
  const statsParts: string[] = [];
92
84
  if (totals.input) statsParts.push(`↑${formatTokens(totals.input)}`);
@@ -97,15 +89,6 @@ export default function (pi: ExtensionAPI) {
97
89
  statsParts.push(`CH${latestCacheHitRate.toFixed(0)}%`);
98
90
  }
99
91
 
100
- const usingSubscription = model
101
- ? model.provider === 'kimi-coding' ||
102
- (ctx.modelRegistry.isUsingOAuth(model) &&
103
- ctx.modelRegistry.getProvider(model.provider)?.auth.oauth?.isSubscription === true)
104
- : false;
105
- if (totals.cost || usingSubscription) {
106
- statsParts.push(`$${totals.cost.toFixed(2)}${usingSubscription ? ' (sub)' : ''}`);
107
- }
108
-
109
92
  const contextDisplay =
110
93
  contextPercent === '?'
111
94
  ? `?/${formatTokens(contextWindow)}`
@@ -118,41 +101,9 @@ export default function (pi: ExtensionAPI) {
118
101
  statsParts.push(`${theme.fg('dim', '•')} ${theme.bold(theme.fg('warning', 'xp'))}`);
119
102
  }
120
103
 
121
- let statsLeft = statsParts.join(' ');
122
- let statsLeftWidth = visibleWidth(statsLeft);
123
- if (statsLeftWidth > width) {
124
- statsLeft = truncateToWidth(statsLeft, width, '...');
125
- statsLeftWidth = visibleWidth(statsLeft);
126
- }
127
-
128
- const minPadding = 2;
129
- const modelName = model?.id.replace(/^claude-/, '') || 'no-model';
130
- let right = modelName;
131
- if (model?.reasoning) {
132
- const level = ctx.thinkingLevel || 'off';
133
- right = level === 'off' ? `${modelName} • thinking off` : `${modelName} • ${level}`;
134
- }
135
-
136
- const rightWidth = visibleWidth(right);
137
- let statsLine: string;
138
- if (statsLeftWidth + minPadding + rightWidth <= width) {
139
- statsLine = statsLeft + ' '.repeat(width - statsLeftWidth - rightWidth) + right;
140
- } else {
141
- const available = width - statsLeftWidth - minPadding;
142
- if (available > 0) {
143
- const truncatedRight = truncateToWidth(right, available, '');
144
- const padding = ' '.repeat(
145
- Math.max(0, width - statsLeftWidth - visibleWidth(truncatedRight)),
146
- );
147
- statsLine = statsLeft + padding + truncatedRight;
148
- } else {
149
- statsLine = statsLeft;
150
- }
151
- }
152
-
153
- const remainder = statsLine.slice(statsLeft.length);
154
- const pwdLine = truncateToWidth(theme.fg('dim', pwd), width, theme.fg('dim', '...'));
155
- const lines = [pwdLine, theme.fg('dim', statsLeft) + theme.fg('dim', remainder)];
104
+ const statsLine = truncateToWidth(statsParts.join(' '), width, '...');
105
+ const topLine = truncateToWidth(theme.fg('dim', top), width, theme.fg('dim', '...'));
106
+ const lines = [topLine, theme.fg('dim', statsLine)];
156
107
 
157
108
  const statuses = footerData.getExtensionStatuses();
158
109
  if (statuses.size > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ravshansbox/pi-statusline",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Statusline extension for pi",
5
5
  "license": "MIT",
6
6
  "type": "module",