@rse/ase 0.0.24 → 0.0.26

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.
@@ -11,6 +11,7 @@ import { InvalidArgumentError } from "commander";
11
11
  import { execaSync } from "execa";
12
12
  import { Chalk } from "chalk";
13
13
  import { Config, configSchema, parseScope } from "./ase-config.js";
14
+ import pkg from "../package.json" with { type: "json" };
14
15
  /* forced-color chalk instance: stdout is a pipe under Claude Code,
15
16
  so chalk auto-detection would yield level 0; force level 1 to keep
16
17
  emitting ANSI sequences as the original implementation did */
@@ -287,6 +288,7 @@ export default class StatuslineCommand {
287
288
  /* identifier to renderer map: each callback fetches its own information
288
289
  directly from data (or via the lazy helpers above for shared values) */
289
290
  const renderers = {
291
+ /* ==== SCOPE ==== */
290
292
  u: () => {
291
293
  const user = process.env.USER ?? process.env.LOGNAME ?? "unknown";
292
294
  emit(`${prefix("※", "user")}${c.bold(user)}`);
@@ -301,6 +303,7 @@ export default class StatuslineCommand {
301
303
  emit(`${prefix("◉", "task")}${c.bold(taskId)}`);
302
304
  },
303
305
  s: () => emit(`${prefix("⏻", "session")}${c.bold(getSession())}`),
306
+ /* ==== MODEL ==== */
304
307
  m: () => {
305
308
  const model = data.model?.display_name ?? "";
306
309
  emit(`${prefix("⚙", "model")}${c.bold(model)}`);
@@ -313,11 +316,18 @@ export default class StatuslineCommand {
313
316
  const thinking = (data.thinking?.enabled ?? false) === true ? "yes" : "no";
314
317
  emit(`${prefix("⚛", "thinking")}${c.bold(thinking)}`);
315
318
  },
319
+ /* ==== OUTPUT ==== */
320
+ O: () => {
321
+ const styleName = data.output_style?.name ?? "";
322
+ if (styleName !== "")
323
+ emit(`${prefix("≡", "style")}${c.bold(styleName)}`);
324
+ },
316
325
  P: () => {
317
326
  const { persona } = getCfg();
318
327
  if (persona !== "")
319
328
  emit(`${prefix("☯", "persona")}${c.bold(persona)}`);
320
329
  },
330
+ /* ==== CONTEXT ==== */
321
331
  c: () => {
322
332
  const pct = Math.floor(data.context_window?.used_percentage ?? 0);
323
333
  const barSize = 20;
@@ -325,38 +335,15 @@ export default class StatuslineCommand {
325
335
  const bar = "█".repeat(filled) + "░".repeat(barSize - filled);
326
336
  emit(`${prefix("◔", "context")}${bar} ${pct}%`);
327
337
  },
328
- a: () => {
329
- const linesAdded = data.cost?.total_lines_added ?? 0;
330
- emit(`${prefix("⊕", "added")}${c.bold(linesAdded)}`);
331
- },
332
- r: () => {
333
- const linesRemoved = data.cost?.total_lines_removed ?? 0;
334
- emit(`${prefix("⊖", "removed")}${c.bold(linesRemoved)}`);
335
- },
336
338
  C: () => {
337
- const ctxIn = data.context_window?.current_usage?.input_tokens ?? 0;
338
- const ctxCcIn = data.context_window?.current_usage?.cache_creation_input_tokens ?? 0;
339
- const ctxCrIn = data.context_window?.current_usage?.cache_read_input_tokens ?? 0;
340
- const tokensCur = ctxIn + ctxCcIn + ctxCrIn;
341
- if (tokensCur > 0)
342
- emit(`${prefix("◇", "tokens")}${c.bold(formatTokens(tokensCur))}`);
343
- },
344
- L: () => {
345
- const pct = Math.floor(data.context_window?.used_percentage ?? 0);
346
- const ctxIn = data.context_window?.current_usage?.input_tokens ?? 0;
347
- const ctxCcIn = data.context_window?.current_usage?.cache_creation_input_tokens ?? 0;
348
- const ctxCrIn = data.context_window?.current_usage?.cache_read_input_tokens ?? 0;
349
- const tokensCur = ctxIn + ctxCcIn + ctxCrIn;
350
- const tokensLim = pct > 0 && tokensCur > 0 ? Math.round(tokensCur * 100 / pct) : 0;
351
- if (tokensLim > 0)
352
- emit(`${prefix("◆", "limit")}${c.bold(formatTokens(tokensLim))}`);
353
- },
354
- N: () => {
355
- const tokensCum = (data.context_window?.total_input_tokens ?? 0) +
339
+ const context = Math.floor(data.context_window?.used_percentage ?? 0);
340
+ const tokensCur = (data.context_window?.total_input_tokens ?? 0) +
356
341
  (data.context_window?.total_output_tokens ?? 0);
357
- if (tokensCum > 0)
358
- emit(`${prefix("Σ", "total")}${c.bold(formatTokens(tokensCum))}`);
342
+ const tokensLim = context > 0 && tokensCur > 0 ? Math.round(tokensCur * 100 / context) : 0;
343
+ if (tokensLim > 0)
344
+ emit(`${prefix("◆", "tokens")}${c.bold(formatTokens(tokensCur) + "/" + formatTokens(tokensLim))}`);
359
345
  },
346
+ /* ==== RATE LIMITS ==== */
360
347
  S: () => {
361
348
  const pct5h = data.rate_limits?.five_hour?.used_percentage;
362
349
  if (pct5h !== undefined)
@@ -379,6 +366,7 @@ export default class StatuslineCommand {
379
366
  if (s !== "")
380
367
  emit(`${prefix("⏱", "weekly-resets")}${c.bold(s)}`);
381
368
  },
369
+ /* ==== COSTS ==== */
382
370
  H: () => {
383
371
  const sessDurMs = data.cost?.total_duration_ms ?? 0;
384
372
  if (sessDurMs > 0)
@@ -389,6 +377,15 @@ export default class StatuslineCommand {
389
377
  if (sessCost !== undefined)
390
378
  emit(`${prefix("$", "cost")}${c.bold(formatCostUsd(sessCost))}`);
391
379
  },
380
+ /* ==== VERSION CONTROL ==== */
381
+ a: () => {
382
+ const linesAdded = data.cost?.total_lines_added ?? 0;
383
+ emit(`${prefix("⊕", "added")}${c.bold(linesAdded)}`);
384
+ },
385
+ r: () => {
386
+ const linesRemoved = data.cost?.total_lines_removed ?? 0;
387
+ emit(`${prefix("⊖", "removed")}${c.bold(linesRemoved)}`);
388
+ },
392
389
  b: () => {
393
390
  const g = getGit();
394
391
  const label = g.branch !== "" ? g.branch : "no git";
@@ -409,20 +406,22 @@ export default class StatuslineCommand {
409
406
  if (cwd !== "")
410
407
  emit(`${prefix("▶", "cwd")}${c.bold(cwd)}`);
411
408
  },
409
+ /* ==== RESOURCES ==== */
412
410
  M: () => {
413
411
  const m = getMem();
414
412
  if (m.total > 0)
415
413
  emit(`${prefix("⛁", "mem")}${c.bold(`${formatBytes(m.used)}/${formatBytes(m.total)}`)}`);
416
414
  },
415
+ /* ==== VERSIONS ==== */
417
416
  V: () => {
418
417
  const ccVersion = data.version ?? "";
418
+ const aseVersion = pkg.version ?? "";
419
+ let version = "";
419
420
  if (ccVersion !== "")
420
- emit(`${prefix("⎈", "version")}${c.bold(ccVersion)}`);
421
- },
422
- o: () => {
423
- const styleName = data.output_style?.name ?? "";
424
- if (styleName !== "")
425
- emit(`${prefix("≡", "style")}${c.bold(styleName)}`);
421
+ version += `claude/${ccVersion}`;
422
+ if (aseVersion !== "")
423
+ version += `${version !== "" ? " " : ""}ase/${aseVersion}`;
424
+ emit(`${prefix("⎈", "version")}${c.bold(version)}`);
426
425
  }
427
426
  };
428
427
  /* walk each template line and render */
@@ -3,7 +3,7 @@
3
3
  ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
4
  ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
5
5
  */
6
- import { execa } from "execa";
6
+ import updateNotifier from "update-notifier";
7
7
  import pkg from "../package.json" with { type: "json" };
8
8
  /* determination of current and available ASE versions */
9
9
  export default class Version {
@@ -13,15 +13,10 @@ export default class Version {
13
13
  }
14
14
  /* return latest ASE version available on the NPM registry */
15
15
  static async latest() {
16
- let latest = "";
17
- try {
18
- const r = await execa("npm", ["view", "@rse/ase", "version"], { stdio: ["ignore", "pipe", "pipe"] });
19
- latest = r.stdout.trim();
20
- }
21
- catch (err) {
22
- const message = err instanceof Error ? err.message : String(err);
23
- throw new Error(`failed to query latest ASE version: ${message}`, { cause: err });
24
- }
25
- return latest;
16
+ const notifier = updateNotifier({
17
+ pkg,
18
+ updateCheckInterval: 1000 * 60 * 60
19
+ });
20
+ return notifier.update?.latest ?? Version.current();
26
21
  }
27
22
  }
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "homepage": "http://github.com/rse/ase",
7
7
  "repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
8
8
  "bugs": { "url": "http://github.com/rse/ase/issues" },
9
- "version": "0.0.24",
9
+ "version": "0.0.26",
10
10
  "license": "GPL-3.0-only",
11
11
  "author": {
12
12
  "name": "Dr. Ralf S. Engelschall",
@@ -18,8 +18,8 @@
18
18
  "devDependencies": {
19
19
  "eslint": "9.39.4",
20
20
  "@eslint/js": "9.39.4",
21
- "@typescript-eslint/parser": "8.59.2",
22
- "@typescript-eslint/eslint-plugin": "8.59.2",
21
+ "@typescript-eslint/parser": "8.59.3",
22
+ "@typescript-eslint/eslint-plugin": "8.59.3",
23
23
  "eslint-plugin-promise": "7.3.0",
24
24
  "eslint-plugin-import": "2.32.0",
25
25
  "neostandard": "0.13.0",
@@ -30,13 +30,14 @@
30
30
  "nodemon": "3.1.14",
31
31
  "shx": "0.4.0",
32
32
 
33
- "@types/node": "25.6.0",
33
+ "@types/node": "25.7.0",
34
34
  "@types/luxon": "3.7.1",
35
- "@types/which": "3.0.4"
35
+ "@types/which": "3.0.4",
36
+ "@types/update-notifier": "6.0.8"
36
37
  },
37
38
  "dependencies": {
38
39
  "commander": "14.0.3",
39
- "yaml": "2.8.4",
40
+ "yaml": "2.9.0",
40
41
  "valibot": "1.4.0",
41
42
  "execa": "9.6.1",
42
43
  "mkdirp": "3.0.1",
@@ -49,11 +50,12 @@
49
50
  "luxon": "3.7.2",
50
51
  "@modelcontextprotocol/sdk": "1.29.0",
51
52
  "zod": "4.4.3",
52
- "which": "6.0.1"
53
+ "which": "7.0.0",
54
+ "update-notifier": "7.3.1"
53
55
  },
54
56
  "engines": {
55
57
  "npm": ">=10.0.0",
56
- "node": ">=20.0.0"
58
+ "node": ">=22.0.0"
57
59
  },
58
60
  "upd": [ "!eslint", "!@eslint/js" ],
59
61
  "files": [