agy-powerline 1.6.0 → 1.8.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.
- package/CHANGELOG.md +27 -0
- package/README.fr.md +10 -0
- package/package.json +1 -1
- package/src/cli/bundle.js +3 -0
- package/src/cli/caps.js +3 -0
- package/src/cli/config-guard.js +3 -0
- package/src/cli/configure.js +17 -0
- package/src/cli/doctor.js +16 -1
- package/src/cli/export.js +3 -0
- package/src/cli/gradient.js +3 -0
- package/src/cli/import.js +3 -0
- package/src/cli/init.js +18 -1
- package/src/cli/layout.js +3 -0
- package/src/cli/preset.js +3 -0
- package/src/cli/repo-url.js +3 -0
- package/src/cli/report.js +3 -0
- package/src/cli/theme.js +3 -0
- package/src/cli/tui-style.js +3 -0
- package/src/cli/uninstall.js +3 -0
- package/src/index.js +15 -0
- package/src/lib/catalog.js +3 -0
- package/src/lib/colors.js +3 -0
- package/src/lib/config-check.js +3 -0
- package/src/lib/config.js +17 -1
- package/src/lib/exec.js +9 -8
- package/src/lib/fit.js +3 -0
- package/src/lib/formatters.js +20 -14
- package/src/lib/git.js +3 -0
- package/src/lib/i18n.js +143 -0
- package/src/lib/layouts/lines.js +20 -11
- package/src/lib/layouts/pills.js +23 -16
- package/src/lib/log.js +3 -0
- package/src/lib/mock-data.js +3 -0
- package/src/lib/paths.js +4 -0
- package/src/lib/payload-dump.js +3 -0
- package/src/lib/powerline.js +3 -0
- package/src/lib/prompt.js +3 -0
- package/src/lib/run.js +3 -0
- package/src/lib/session.js +24 -17
- package/src/lib/shared.js +3 -0
- package/src/lib/themes.js +3 -0
- package/src/lib/usage.js +3 -0
- package/src/lib/widget-options.js +3 -0
- package/src/lib/widget-style.js +46 -38
- package/src/runtime/statusline.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.8.0] - 2026-10-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Each GitHub release has its signed SLSA provenance attached as `agy-powerline-<version>.intoto.jsonl`, next to the `.sigstore.json` attestations
|
|
13
|
+
- GOVERNANCE.md (roles, how decisions are made, continuity), ROADMAP.md (plans to October 2027) and SECURITY-REVIEW.md (the first security review and its findings); SECURITY.md says how vulnerability reports are handled and credited and gives the project's assurance case
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- The README screenshots and agy-powerline.com's images are smaller files, and the home page fetches its hero artwork first
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- agy-powerline.com's sitemap lists the screenshots at the addresses the site serves them from
|
|
22
|
+
|
|
23
|
+
## [1.7.0] - 2026-10-24
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- `"language"` setting for the bar's own words (labels, `rem`, units), set with `init --language` or tried with `render --language`; a code without messages shows English (#102)
|
|
28
|
+
- The bar in French with `"language": "fr"`, and agy-powerline.com/fr/ shows its bars in French (#148)
|
|
29
|
+
- agy-powerline.com/.well-known/security.txt sends security reports to GitHub's private vulnerability reporting
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- agy-powerline.com loads smaller images: each screenshot comes in smaller copies the browser picks from by the width it shows, the feature icons have a 56 px version, and the WebP images carry no color profile
|
|
34
|
+
|
|
8
35
|
## [1.6.0] - 2026-10-24
|
|
9
36
|
|
|
10
37
|
### Added
|
package/README.fr.md
CHANGED
|
@@ -135,6 +135,16 @@ Prévisualisez tous les thèmes avec `npx agy-powerline theme --gallery`.
|
|
|
135
135
|
|
|
136
136
|
</details>
|
|
137
137
|
|
|
138
|
+
### Langue de la barre
|
|
139
|
+
|
|
140
|
+
Les mots de la barre elle-même (`Réinit`, `rest.`, les unités de `2h 47m`) peuvent s’afficher en français :
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
npx agy-powerline init --language fr
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
ou `"language": "fr"` dans `statusline.config.json` (touche `u` dans `configure`). Le nom du modèle, la branche et tout ce qu’envoie agy restent tels quels ; les commandes et `configure` restent en anglais. Détails dans la [documentation de configuration](docs/configuration.md#language).
|
|
147
|
+
|
|
138
148
|
## Widgets
|
|
139
149
|
|
|
140
150
|
| Widget | Informations affichées |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agy-powerline",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "agy statusline for Google Antigravity CLI: live Gemini, Claude/GPT and Argon quota pacing, git, themes and an interactive TUI configurator",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agy-powerline": "src/index.js"
|
package/src/cli/bundle.js
CHANGED
package/src/cli/caps.js
CHANGED
package/src/cli/config-guard.js
CHANGED
package/src/cli/configure.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const readline = require("readline");
|
|
@@ -24,6 +27,7 @@ const {
|
|
|
24
27
|
} = require("../lib/shared");
|
|
25
28
|
const { resolveInstallDir } = require("../lib/paths");
|
|
26
29
|
const { WIDGET_TAGS } = require("../lib/widget-style");
|
|
30
|
+
const { SUPPORTED_LANGUAGES, resolveLanguage } = require("../lib/i18n");
|
|
27
31
|
const { editFields: getEditFields, stepNumberField } = require("../lib/widget-options");
|
|
28
32
|
const { loadEditableConfig } = require("./config-guard");
|
|
29
33
|
const {
|
|
@@ -427,6 +431,10 @@ function previewParts(width) {
|
|
|
427
431
|
if (preview.layout === "pills") {
|
|
428
432
|
chips.unshift(ui.chip("joins", preview.powerline.enabled, key("j")));
|
|
429
433
|
}
|
|
434
|
+
// Only worth a chip once there is a language to switch to.
|
|
435
|
+
if (SUPPORTED_LANGUAGES.length > 1) {
|
|
436
|
+
chips.push(ui.chip(`lang ${resolveLanguage(preview.language)}`, true, key("u")));
|
|
437
|
+
}
|
|
430
438
|
|
|
431
439
|
return { title, bar: String(rendered).split("\n"), chips: chips.join(" ") };
|
|
432
440
|
}
|
|
@@ -1629,6 +1637,15 @@ function onMain(key) {
|
|
|
1629
1637
|
if (persist()) {
|
|
1630
1638
|
flashMessage = `Pace marker: ${config.pacing ? "on" : "off"}`;
|
|
1631
1639
|
}
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
if (key.name === "u" && SUPPORTED_LANGUAGES.length > 1) {
|
|
1644
|
+
const next = SUPPORTED_LANGUAGES.indexOf(resolveLanguage(config.language)) + 1;
|
|
1645
|
+
config.language = SUPPORTED_LANGUAGES[next % SUPPORTED_LANGUAGES.length];
|
|
1646
|
+
if (persist()) {
|
|
1647
|
+
flashMessage = `Bar language: ${config.language}`;
|
|
1648
|
+
}
|
|
1632
1649
|
}
|
|
1633
1650
|
}
|
|
1634
1651
|
|
package/src/cli/doctor.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const fs = require("fs");
|
|
@@ -28,6 +31,7 @@ const { runStatuslineCommand } = require("../lib/run");
|
|
|
28
31
|
const { detectColorDepth } = require("../lib/colors");
|
|
29
32
|
const { readLog, getLogPath } = require("../lib/log");
|
|
30
33
|
const { USAGE_PERIODS, usageAvailable } = require("../lib/usage");
|
|
34
|
+
const { matchLanguage, SUPPORTED_LANGUAGES } = require("../lib/i18n");
|
|
31
35
|
const { version } = require("../../package.json");
|
|
32
36
|
|
|
33
37
|
const DIM = "\x1b[2m";
|
|
@@ -78,7 +82,7 @@ function stripAnsi(text) {
|
|
|
78
82
|
function renderOverridesInCommand(command) {
|
|
79
83
|
const names = [];
|
|
80
84
|
const pattern =
|
|
81
|
-
/(?:^|\s)--(preset|layout|theme|caps|gradient)(?:(?:\s*=\s*|\s+)(?:"([^"]*)"|'([^']*)'|([^\s-][^\s]*)))?/g;
|
|
85
|
+
/(?:^|\s)--(preset|layout|theme|caps|gradient|language)(?:(?:\s*=\s*|\s+)(?:"([^"]*)"|'([^']*)'|([^\s-][^\s]*)))?/g;
|
|
82
86
|
|
|
83
87
|
for (const match of String(command).matchAll(pattern)) {
|
|
84
88
|
const value = match[2] ?? match[3] ?? match[4] ?? "(missing)";
|
|
@@ -193,6 +197,17 @@ async function doctorCommand(options = {}) {
|
|
|
193
197
|
console.log(" tokensToday and tokensWeek stay hidden until Node is updated.");
|
|
194
198
|
}
|
|
195
199
|
|
|
200
|
+
// Not a failure either: the bar shows English.
|
|
201
|
+
const language = configState.raw?.language;
|
|
202
|
+
if (language !== undefined && !matchLanguage(language)) {
|
|
203
|
+
const shown = String(language)
|
|
204
|
+
.replace(/[^A-Za-z0-9_-]/g, "?")
|
|
205
|
+
.slice(0, 32);
|
|
206
|
+
console.log();
|
|
207
|
+
console.log(`${YELLOW} language "${shown}" isn't available${RESET}, so the bar shows English.`);
|
|
208
|
+
console.log(` Available: ${SUPPORTED_LANGUAGES.join(", ")}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
196
211
|
const breaking = cmdBreakingChars(installDir);
|
|
197
212
|
if (breaking.length) {
|
|
198
213
|
failed += 1;
|
package/src/cli/export.js
CHANGED
package/src/cli/gradient.js
CHANGED
package/src/cli/import.js
CHANGED
package/src/cli/init.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const fs = require("fs");
|
|
@@ -19,6 +22,7 @@ const {
|
|
|
19
22
|
THEME_ORDER,
|
|
20
23
|
canonicalThemeId,
|
|
21
24
|
} = require("../lib/shared");
|
|
25
|
+
const { matchLanguage, SUPPORTED_LANGUAGES } = require("../lib/i18n");
|
|
22
26
|
const {
|
|
23
27
|
AGY_SETTINGS,
|
|
24
28
|
RUNTIME_FILES,
|
|
@@ -89,7 +93,7 @@ function unknownChoice(kind, value, ids) {
|
|
|
89
93
|
return null;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
// --preset, --layout and --
|
|
96
|
+
// --preset, --layout, --theme and --language, checked before anything is written. Returns
|
|
93
97
|
// the ids given ({} for none), or null after printing what's wrong.
|
|
94
98
|
function readChoiceFlags(options) {
|
|
95
99
|
const choices = {};
|
|
@@ -113,6 +117,16 @@ function readChoiceFlags(options) {
|
|
|
113
117
|
}
|
|
114
118
|
choices.theme = theme;
|
|
115
119
|
}
|
|
120
|
+
if (options.language !== undefined) {
|
|
121
|
+
const language = matchLanguage(options.language);
|
|
122
|
+
if (!language) {
|
|
123
|
+
console.error(`${RED}error${RESET} Unknown language "${options.language}".`);
|
|
124
|
+
console.error(` Available languages: ${SUPPORTED_LANGUAGES.join(", ")}`);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
choices.language = language;
|
|
129
|
+
}
|
|
116
130
|
return choices;
|
|
117
131
|
}
|
|
118
132
|
|
|
@@ -124,6 +138,9 @@ function applyChoices(config, choices) {
|
|
|
124
138
|
if (choices.theme) {
|
|
125
139
|
next.theme = choices.theme;
|
|
126
140
|
}
|
|
141
|
+
if (choices.language) {
|
|
142
|
+
next.language = choices.language;
|
|
143
|
+
}
|
|
127
144
|
return next;
|
|
128
145
|
}
|
|
129
146
|
|
package/src/cli/layout.js
CHANGED
package/src/cli/preset.js
CHANGED
package/src/cli/repo-url.js
CHANGED
package/src/cli/report.js
CHANGED
package/src/cli/theme.js
CHANGED
package/src/cli/tui-style.js
CHANGED
package/src/cli/uninstall.js
CHANGED
package/src/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
4
|
+
|
|
2
5
|
"use strict";
|
|
3
6
|
|
|
4
7
|
const fs = require("fs");
|
|
@@ -28,6 +31,7 @@ const {
|
|
|
28
31
|
} = require("./lib/shared");
|
|
29
32
|
const { STYLE_ORDER } = require("./lib/powerline");
|
|
30
33
|
const { GRADIENT_ORDER } = require("./lib/themes");
|
|
34
|
+
const { SUPPORTED_LANGUAGES } = require("./lib/i18n");
|
|
31
35
|
const { stripControl } = require("./lib/formatters");
|
|
32
36
|
const { resolveInstallDir, isTrustedInstallDir } = require("./lib/paths");
|
|
33
37
|
const { isLogEnabled, setLogDir, logError, jsonErrorMessage } = require("./lib/log");
|
|
@@ -75,6 +79,11 @@ const COMMANDS = [
|
|
|
75
79
|
value: "<id>",
|
|
76
80
|
help: "use this theme, or dark, light, colorblind (skips the question)",
|
|
77
81
|
},
|
|
82
|
+
language: {
|
|
83
|
+
type: "string",
|
|
84
|
+
value: "<code>",
|
|
85
|
+
help: `show the bar in this language (${SUPPORTED_LANGUAGES.join(", ")})`,
|
|
86
|
+
},
|
|
78
87
|
},
|
|
79
88
|
run: (_arg, opts) =>
|
|
80
89
|
initCommand({
|
|
@@ -232,6 +241,11 @@ const COMMANDS = [
|
|
|
232
241
|
value: "<name|colors>",
|
|
233
242
|
help: "use a gradient preset, hex stops, or off",
|
|
234
243
|
},
|
|
244
|
+
language: {
|
|
245
|
+
type: "string",
|
|
246
|
+
value: "<code>",
|
|
247
|
+
help: `use a language for this render (${SUPPORTED_LANGUAGES.join(", ")})`,
|
|
248
|
+
},
|
|
235
249
|
"dump-payload": {
|
|
236
250
|
type: "string",
|
|
237
251
|
value: "<path>",
|
|
@@ -384,6 +398,7 @@ function renderOverrideError(name, value) {
|
|
|
384
398
|
preset: ["preset", `Available presets: ${PRESET_ORDER.join(", ")}`],
|
|
385
399
|
caps: ["cap style", `Available styles: ${STYLE_ORDER.join(", ")}`],
|
|
386
400
|
gradient: ["gradient", `Available gradients: ${GRADIENT_ORDER.join(", ")}, off`],
|
|
401
|
+
language: ["language", `Available languages: ${SUPPORTED_LANGUAGES.join(", ")}`],
|
|
387
402
|
}[name];
|
|
388
403
|
console.error(`${RED}error${RESET} Unknown ${what} "${stripControl(String(value))}".`);
|
|
389
404
|
console.error(` ${list}`);
|
package/src/lib/catalog.js
CHANGED
package/src/lib/colors.js
CHANGED
package/src/lib/config-check.js
CHANGED
package/src/lib/config.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const fs = require("fs");
|
|
@@ -8,6 +11,7 @@ const { stripControl, normalizeClock } = require("./formatters");
|
|
|
8
11
|
const { normalizePowerline, applyStyle, STYLES } = require("./powerline");
|
|
9
12
|
const { writeFileAtomic, PRIVATE_FILE_MODE } = require("./paths");
|
|
10
13
|
const { isMeterStyle } = require("./widget-style");
|
|
14
|
+
const { resolveLanguage, matchLanguage } = require("./i18n");
|
|
11
15
|
|
|
12
16
|
// Display text in widget configs is printed as-is, so strip terminal control
|
|
13
17
|
// from it. cmd/command are left alone: they are executed, not printed.
|
|
@@ -126,6 +130,7 @@ function defaultConfig() {
|
|
|
126
130
|
ascii: false,
|
|
127
131
|
color: "auto",
|
|
128
132
|
layout: "pills",
|
|
133
|
+
language: "en",
|
|
129
134
|
pacing: true,
|
|
130
135
|
minimalist: false,
|
|
131
136
|
rowGap: false,
|
|
@@ -185,6 +190,8 @@ function mergeConfig(raw) {
|
|
|
185
190
|
ascii: raw?.ascii === true,
|
|
186
191
|
color: resolveColorModeId(raw?.color ?? fallback.color),
|
|
187
192
|
layout: resolveLayoutId(raw?.layout ?? fallback.layout),
|
|
193
|
+
// A language without messages shows English (fr-FR uses fr when there is one).
|
|
194
|
+
language: resolveLanguage(raw?.language),
|
|
188
195
|
pacing: raw?.pacing !== false,
|
|
189
196
|
minimalist: raw?.minimalist === true,
|
|
190
197
|
rowGap: raw?.rowGap === true,
|
|
@@ -237,7 +244,7 @@ function readConfigFile() {
|
|
|
237
244
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
238
245
|
return { exists: true, config: defaultConfig(), error: "top-level value is not an object" };
|
|
239
246
|
}
|
|
240
|
-
return { exists: true, config: mergeConfig(raw) };
|
|
247
|
+
return { exists: true, config: mergeConfig(raw), raw };
|
|
241
248
|
} catch (err) {
|
|
242
249
|
// Newer Node quotes part of the file in the message; it may hold anything.
|
|
243
250
|
return { exists: true, config: defaultConfig(), error: stripControl(err.message) };
|
|
@@ -475,6 +482,15 @@ function applyRenderOverrides(baseConfig, overrides = {}) {
|
|
|
475
482
|
}
|
|
476
483
|
}
|
|
477
484
|
|
|
485
|
+
if (overrides.language !== undefined) {
|
|
486
|
+
const language = matchLanguage(overrides.language);
|
|
487
|
+
if (language) {
|
|
488
|
+
config = mergeConfig({ ...config, language });
|
|
489
|
+
} else {
|
|
490
|
+
invalid.push("language");
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
478
494
|
return { config, invalid };
|
|
479
495
|
}
|
|
480
496
|
|
package/src/lib/exec.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const fs = require("fs");
|
|
@@ -8,6 +11,7 @@ const { execSync } = require("child_process");
|
|
|
8
11
|
const { stripControl, sanitizeDeep } = require("./formatters");
|
|
9
12
|
const { RESET, getActiveDepth } = require("./colors");
|
|
10
13
|
const { logWarning } = require("./log");
|
|
14
|
+
const { t } = require("./i18n");
|
|
11
15
|
const { PRIVATE_FILE_MODE } = require("./paths");
|
|
12
16
|
|
|
13
17
|
const DEFAULT_TIMEOUT_MS = 500;
|
|
@@ -15,10 +19,6 @@ const DEFAULT_INTERVAL_SEC = 10;
|
|
|
15
19
|
const MAX_CACHE_AGE_SEC = 3600;
|
|
16
20
|
const MAX_OUTPUT_CHARS = 80;
|
|
17
21
|
|
|
18
|
-
// Placeholders shown instead of running the command.
|
|
19
|
-
const EXEC_PREVIEW_TEXT = "[cmd]";
|
|
20
|
-
const EXEC_BLOCKED_TEXT = "[blocked]";
|
|
21
|
-
|
|
22
22
|
const memoryCache = new Map();
|
|
23
23
|
|
|
24
24
|
function getCacheFilePath() {
|
|
@@ -31,7 +31,9 @@ function getCacheFilePath() {
|
|
|
31
31
|
} catch {
|
|
32
32
|
// Fallback
|
|
33
33
|
}
|
|
34
|
-
// Per-user name so
|
|
34
|
+
// Per-user name so accounts don't share one cache. Another account could
|
|
35
|
+
// still guess and pre-create it in a shared /tmp, so the runtime never comes
|
|
36
|
+
// here: exec widgets only run from a config file in the install dir above.
|
|
35
37
|
let user = "user";
|
|
36
38
|
try {
|
|
37
39
|
user = os.userInfo().username.replace(/[^A-Za-z0-9_.-]/g, "_") || user;
|
|
@@ -233,7 +235,8 @@ function execWidgetOutput(widget, session = {}) {
|
|
|
233
235
|
return output;
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
|
|
238
|
+
// Placeholders shown instead of running the command.
|
|
239
|
+
return t(session.execMode === "blocked" ? "cmd_blocked" : "cmd_preview", session.lang);
|
|
237
240
|
}
|
|
238
241
|
|
|
239
242
|
function runExecWidget(widget, session = {}) {
|
|
@@ -349,6 +352,4 @@ module.exports = {
|
|
|
349
352
|
saveDiskCache,
|
|
350
353
|
DEFAULT_TIMEOUT_MS,
|
|
351
354
|
DEFAULT_INTERVAL_SEC,
|
|
352
|
-
EXEC_PREVIEW_TEXT,
|
|
353
|
-
EXEC_BLOCKED_TEXT,
|
|
354
355
|
};
|
package/src/lib/fit.js
CHANGED
package/src/lib/formatters.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2026 agy-powerline contributors
|
|
3
|
+
|
|
1
4
|
"use strict";
|
|
2
5
|
|
|
3
6
|
const os = require("os");
|
|
4
7
|
const path = require("path");
|
|
5
8
|
const { rgb } = require("./colors");
|
|
9
|
+
const { t } = require("./i18n");
|
|
6
10
|
|
|
7
|
-
function formatReset(seconds) {
|
|
11
|
+
function formatReset(seconds, lang) {
|
|
8
12
|
seconds = Number(seconds);
|
|
9
13
|
|
|
10
14
|
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
11
|
-
return "now";
|
|
15
|
+
return t("now", lang);
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
const totalMinutes = Math.floor(seconds / 60);
|
|
@@ -17,23 +21,23 @@ function formatReset(seconds) {
|
|
|
17
21
|
const minutes = totalMinutes % 60;
|
|
18
22
|
|
|
19
23
|
if (days > 0) {
|
|
20
|
-
return `${days}
|
|
24
|
+
return `${days}${t("unit_d", lang)} ${hours}${t("unit_h", lang)}`;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
if (hours > 0) {
|
|
24
|
-
return `${hours}
|
|
28
|
+
return `${hours}${t("unit_hr", lang)} ${minutes}${t("unit_m", lang)}`;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
return `${Math.max(1, minutes)}
|
|
31
|
+
return `${Math.max(1, minutes)}${t("unit_m", lang)}`;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
function formatSessionTime(startMs, nowMs = Date.now()) {
|
|
34
|
+
function formatSessionTime(startMs, nowMs = Date.now(), lang) {
|
|
31
35
|
const start = Number(startMs);
|
|
32
36
|
const now = Number(nowMs);
|
|
33
37
|
if (!Number.isFinite(start) || start <= 0 || !Number.isFinite(now) || now - start < 60000) {
|
|
34
38
|
return "";
|
|
35
39
|
}
|
|
36
|
-
return formatReset((now - start) / 1000);
|
|
40
|
+
return formatReset((now - start) / 1000, lang);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const MONTHS_SHORT = [
|
|
@@ -274,22 +278,22 @@ function shortModelName(name, ascii = false) {
|
|
|
274
278
|
}
|
|
275
279
|
|
|
276
280
|
// Session input and output tokens: "88.2K↑ 61.1K↓", or "88.2K in 61.1K out".
|
|
277
|
-
function formatTokenSplit(input, output, ascii = false) {
|
|
281
|
+
function formatTokenSplit(input, output, ascii = false, lang) {
|
|
278
282
|
return ascii
|
|
279
|
-
? `${formatTokens(input)}
|
|
283
|
+
? `${formatTokens(input)} ${t("tokens_in", lang)} ${formatTokens(output)} ${t("tokens_out", lang)}`
|
|
280
284
|
: `${formatTokens(input)}↑ ${formatTokens(output)}↓`;
|
|
281
285
|
}
|
|
282
286
|
|
|
283
287
|
// The usage widgets' text: "1.2M", or "1.0M↑ 245.3K↓" with "split", plus the
|
|
284
288
|
// share of a "budget" when one is set ("1.2M (60%)"). null with no tokens.
|
|
285
|
-
function formatUsage(tokens, widget = {}, ascii = false) {
|
|
289
|
+
function formatUsage(tokens, widget = {}, ascii = false, lang) {
|
|
286
290
|
const input = Number(tokens?.input) || 0;
|
|
287
291
|
const output = Number(tokens?.output) || 0;
|
|
288
292
|
const total = input + output;
|
|
289
293
|
if (!(total > 0)) {
|
|
290
294
|
return null;
|
|
291
295
|
}
|
|
292
|
-
const value = widget?.split ? formatTokenSplit(input, output, ascii) : formatTokens(total);
|
|
296
|
+
const value = widget?.split ? formatTokenSplit(input, output, ascii, lang) : formatTokens(total);
|
|
293
297
|
const budget = widget?.budget;
|
|
294
298
|
const pct =
|
|
295
299
|
typeof budget === "number" && Number.isFinite(budget) && budget > 0
|
|
@@ -620,9 +624,11 @@ function formatGitOperation(op) {
|
|
|
620
624
|
}
|
|
621
625
|
|
|
622
626
|
// "2 subagents, 1 task", or "" when nothing runs.
|
|
623
|
-
function formatTasks(subagents, tasks) {
|
|
624
|
-
const part = (n,
|
|
625
|
-
return [part(subagents, "subagent"), part(tasks, "task"
|
|
627
|
+
function formatTasks(subagents, tasks, lang) {
|
|
628
|
+
const part = (n, one, many) => (n > 0 ? `${n} ${t(n === 1 ? one : many, lang)}` : "");
|
|
629
|
+
return [part(subagents, "subagent", "subagents"), part(tasks, "task", "tasks")]
|
|
630
|
+
.filter(Boolean)
|
|
631
|
+
.join(", ");
|
|
626
632
|
}
|
|
627
633
|
|
|
628
634
|
// "accept-edits, NORMAL", or "" in the default mode with Vim editing off.
|