tachograph 0.10.5 → 0.10.6

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 +1 -1
  2. package/install.js +44 -7
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -14,7 +14,7 @@ tacho setup claude # print the Claude Code statusLine config (--write install
14
14
  matching [GitHub release](https://github.com/kosako/tachograph/releases)
15
15
  (macOS / Linux / Windows, x64 or arm64) and verifies it against the release's
16
16
  `checksums.txt`. The download runs in the package's postinstall script
17
- (Node.js 18+), so installing with `--ignore-scripts` leaves no binary. If no
17
+ (Node.js 22+), so installing with `--ignore-scripts` leaves no binary. If no
18
18
  prebuilt binary fits your platform, install from source instead:
19
19
 
20
20
  ```sh
package/install.js CHANGED
@@ -21,24 +21,61 @@ const binDir = path.join(__dirname, "bin");
21
21
  // at the go-install fallback.
22
22
  const FETCH_TIMEOUT_MS = 120_000;
23
23
 
24
- // fetchBuffer downloads url fully and maps failures (HTTP errors, timeouts)
25
- // to messages that name what was being fetched.
24
+ // fetchBuffer downloads url fully and maps failures (HTTP errors, timeouts,
25
+ // network errors) to messages that name what was being fetched and why.
26
26
  async function fetchBuffer(url, what) {
27
+ let res;
27
28
  try {
28
- const res = await fetch(url, {
29
+ res = await fetch(url, {
29
30
  redirect: "follow",
30
31
  signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
31
32
  });
32
- if (!res.ok) {
33
- throw new Error(`${what} failed: ${res.status} ${res.statusText} for ${url}`);
33
+ if (res.ok) {
34
+ return Buffer.from(await res.arrayBuffer());
34
35
  }
35
- return Buffer.from(await res.arrayBuffer());
36
36
  } catch (err) {
37
37
  if (err.name === "TimeoutError") {
38
38
  throw new Error(`${what} timed out after ${FETCH_TIMEOUT_MS / 1000}s for ${url}`);
39
39
  }
40
- throw err;
40
+ const reason = causeOf(err);
41
+ throw new Error(`${what} failed: ${err.message}${reason ? ` (${reason})` : ""} for ${url}`);
41
42
  }
43
+ throw new Error(`${what} failed: ${res.status} ${res.statusText} for ${url}`);
44
+ }
45
+
46
+ // causeOf is why fetch failed at the network level (DNS, a refused
47
+ // connection, TLS, a proxy): fetch itself only says "fetch failed" and keeps
48
+ // the reason in err.cause — an error with a code, an AggregateError of one per
49
+ // address tried with an empty message, or a wrapper (a proxy's connection
50
+ // error) whose own cause holds the specifics. Every level of that chain is
51
+ // named, outermost first (#382). Empty when there is none.
52
+ function causeOf(err) {
53
+ const parts = [];
54
+ const seen = new Set();
55
+ for (let c = err.cause, depth = 0; c != null && depth < 5 && !seen.has(c); c = c.cause, depth++) {
56
+ if (typeof c !== "object") {
57
+ parts.push(String(c));
58
+ break;
59
+ }
60
+ seen.add(c);
61
+ const part = describeError(c);
62
+ if (part) parts.push(part);
63
+ }
64
+ return parts.join("; caused by ");
65
+ }
66
+
67
+ // describeError names one error of a cause chain: its message (an
68
+ // AggregateError's is empty, so its errors' messages), with its code in front
69
+ // unless the message already says it.
70
+ function describeError(e) {
71
+ let msg = e.message;
72
+ if (!msg && Array.isArray(e.errors)) {
73
+ msg = e.errors.map((x) => x && x.message).filter(Boolean).join("; ");
74
+ }
75
+ if (e.code && !String(msg).includes(e.code)) {
76
+ msg = msg ? `${e.code}: ${msg}` : e.code;
77
+ }
78
+ return msg || "";
42
79
  }
43
80
 
44
81
  // tarBin picks the extractor. On Windows the zip asset needs bsdtar, but PATH
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tachograph",
3
- "version": "0.10.5",
3
+ "version": "0.10.6",
4
4
  "description": "A compact instrument cluster for your coding agents (Claude Code / Codex). Shows model, rate-limit headroom, and context at a glance.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -32,6 +32,6 @@
32
32
  "test": "node test.js"
33
33
  },
34
34
  "engines": {
35
- "node": ">=18"
35
+ "node": ">=22"
36
36
  }
37
37
  }