agy-powerline 1.2.0 → 1.3.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.
@@ -101,6 +101,11 @@ const WIDGET_TAGS = {
101
101
  cwd: { icon: "📂", name: "Dir" },
102
102
  project: { icon: "📦", name: "Project" },
103
103
  git: { icon: "🌿", name: "" },
104
+ gitChanges: { icon: "📝", name: "Lines" },
105
+ gitFiles: { icon: "📄", name: "Files" },
106
+ gitSha: { icon: "📌", name: "Commit" },
107
+ gitStash: { icon: "💼", name: "Stash" },
108
+ gitWorktree: { icon: "🌳", name: "Worktree" },
104
109
  plan: { icon: "⭐", name: "Plan" },
105
110
  agentState: { icon: "🟣", name: "Agent" },
106
111
  artifacts: { icon: "📎", name: "Artifacts" },
@@ -114,6 +119,8 @@ const WIDGET_TAGS = {
114
119
  cacheCreate: { icon: "📤", name: "Cache create" },
115
120
  cacheHit: { icon: "⚡", name: "Cache hit" },
116
121
  totalTokens: { icon: "🪙", name: "Tokens" },
122
+ tokensToday: { icon: "📈", name: "Today" },
123
+ tokensWeek: { icon: "📊", name: "7d" },
117
124
  customText: { icon: "🏷️", name: "" },
118
125
  };
119
126
 
@@ -132,6 +139,34 @@ function widgetTag(id, { emojis = true, raw = false, icon } = {}) {
132
139
  return `${icon ?? tag.icon} ${tag.iconOnly ? "" : named}`;
133
140
  }
134
141
 
142
+ // Meter styles: [filled, empty] glyphs. cells has none: Pills draws it with
143
+ // background colors. Every glyph is one column wide for visibleWidth(); a
144
+ // two-column glyph would overflow the meter and throw fitting off.
145
+ const METER_STYLES = {
146
+ cells: null,
147
+ dots: ["●", "●"],
148
+ blocks: ["█", "░"],
149
+ shade: ["▓", "░"],
150
+ line: ["━", "─"],
151
+ geometric: ["▰", "▱"],
152
+ squares: ["■", "□"],
153
+ braille: ["⣿", "⣀"],
154
+ bars: ["▮", "▯"],
155
+ };
156
+ const METER_STYLE_IDS = Object.keys(METER_STYLES);
157
+
158
+ function isMeterStyle(value) {
159
+ return typeof value === "string" && Object.hasOwn(METER_STYLES, value);
160
+ }
161
+
162
+ // The widget's "meter", else the global "meterStyle", else the layout's own;
163
+ // cells exists only in Pills, so Lines draws dots instead.
164
+ function meterStyle(widget, config, layout) {
165
+ const own = layout === "lines" ? "dots" : "cells";
166
+ const id = [widget?.meter, config?.meterStyle].find(isMeterStyle) ?? own;
167
+ return id === "cells" ? own : id;
168
+ }
169
+
135
170
  // Longest conversation title shown, in terminal columns.
136
171
  const TITLE_MAX = 30;
137
172
 
@@ -159,6 +194,10 @@ module.exports = {
159
194
  widgetTag,
160
195
  isRaw,
161
196
  isPaced,
197
+ METER_STYLES,
198
+ METER_STYLE_IDS,
199
+ isMeterStyle,
200
+ meterStyle,
162
201
  hasNoData,
163
202
  RAM_CAUTION,
164
203
  RAM_DANGER,
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ "use strict";
3
+
2
4
  const path = require("path");
3
5
  const { readConfigFile, renderStatusline } = require("./shared");
4
6
  const { isTrustedInstallDir } = require("./paths");
@@ -28,6 +30,18 @@ const STDIN_TIMEOUT_MS = 1000;
28
30
  const { config, error: configError } = readConfigFile();
29
31
  setLogDir(__dirname, isLogEnabled(configError ? null : config));
30
32
 
33
+ // Antigravity can close the pipe before the statusline finishes writing. That
34
+ // is a normal shutdown, so don't treat EPIPE as a runtime crash.
35
+ process.stdout.on("error", (err) => {
36
+ if (err?.code === "EPIPE") {
37
+ process.exit(0);
38
+ }
39
+
40
+ logError("RUNTIME_CRASH", err);
41
+ process.stderr.write(`[agy-powerline] ${redact(err?.message || err)}\n`);
42
+ process.exit(0);
43
+ });
44
+
31
45
  // A crash must not leave a stack trace in Antigravity's status bar.
32
46
  process.on("uncaughtException", (err) => {
33
47
  logError("RUNTIME_CRASH", err);
@@ -112,7 +126,7 @@ function render(input, complete) {
112
126
  }
113
127
 
114
128
  const started = Date.now();
115
- const output = renderStatusline(data, config, { exec, configError });
129
+ const output = renderStatusline(data, config, { exec, configError, usage: "read" });
116
130
  const elapsed = Date.now() - started;
117
131
 
118
132
  if (elapsed > SLOW_RENDER_MS) {