bdy 1.24.3-dev → 1.24.4-dev

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.24.3-dev",
4
+ "version": "1.24.4-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",
@@ -12,6 +12,7 @@ class Logger {
12
12
  logPath = null;
13
13
  log1Path = null;
14
14
  logStream = null;
15
+ dest = null;
15
16
  p = null;
16
17
  ts = null;
17
18
  constructor() {
@@ -86,6 +87,24 @@ class Logger {
86
87
  if (this.logPath)
87
88
  this.applyLogRights(this.logPath);
88
89
  const pino = require('pino');
90
+ // Not stdout as a fallback: it is machine-read by `--format json` and the mcp command.
91
+ // `sync`, which pino.destination(fd) does not default to: an asynchronous destination
92
+ // buffers the line and writes it from the threadpool, so the tail of the log is exactly
93
+ // what an agent killed by its service manager - or by the crash being logged - loses,
94
+ // and every descriptor it still holds has to outlive whoever closes it.
95
+ this.dest =
96
+ this.logStream === null
97
+ ? { write: () => { } }
98
+ : pino.destination({
99
+ dest: this.logStream,
100
+ sync: true,
101
+ minLength: 0,
102
+ });
103
+ // A line that could not be written is not worth taking the process down for. Pino's own
104
+ // handler swallows EPIPE and re-emits the rest, and an EventEmitter re-emitting 'error'
105
+ // with nobody listening throws - so an unwritable log used to arrive as a crash.
106
+ // (the ternary above assigns an untyped pino value, which does not narrow the field)
107
+ this.dest.on?.('error', () => { });
89
108
  this.p = pino({
90
109
  level: this.debugOn ? 'debug' : 'info',
91
110
  timestamp: () => `, "time": "${new Date().toISOString()}"`,
@@ -95,11 +114,7 @@ class Logger {
95
114
  level: label.toUpperCase(),
96
115
  }),
97
116
  },
98
- },
99
- // Not stdout as a fallback: it is machine-read by `--format json` and the mcp command
100
- this.logStream === null
101
- ? { write: () => { } }
102
- : pino.destination(this.logStream));
117
+ }, this.dest);
103
118
  this.checkLogSize();
104
119
  this.ts = setInterval(() => {
105
120
  this.checkLogSize();
@@ -122,20 +137,36 @@ class Logger {
122
137
  stack() {
123
138
  this.getPino().info(new Error().stack);
124
139
  }
140
+ // The descriptor belongs to the destination from the moment pino is handed one, so the close
141
+ // goes through the stream rather than through the number: closeSync on the number leaves a
142
+ // live stream holding a descriptor the kernel is free to hand to the next open - an EBADF at
143
+ // best, a log line in an unrelated file at worst - and pino, for a destination it opened
144
+ // asynchronously, flushes it again on exit. Anything still queued goes out first.
145
+ closeDestination() {
146
+ const dest = this.dest;
147
+ this.dest = null;
148
+ this.logStream = null;
149
+ if (!dest)
150
+ return;
151
+ try {
152
+ dest.flushSync?.();
153
+ }
154
+ catch {
155
+ // a destination that never opened, or one with nothing left to write
156
+ }
157
+ try {
158
+ dest.destroy?.();
159
+ }
160
+ catch {
161
+ // do nothing
162
+ }
163
+ }
125
164
  changeRootPath(path) {
126
165
  if (this.ts) {
127
166
  clearInterval(this.ts);
128
167
  this.ts = null;
129
168
  }
130
- if (this.logStream) {
131
- try {
132
- fs_1.default.closeSync(this.logStream);
133
- }
134
- catch {
135
- // do nothing
136
- }
137
- this.logStream = null;
138
- }
169
+ this.closeDestination();
139
170
  this.p = null;
140
171
  this.rootPath = path;
141
172
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.24.3-dev",
4
+ "version": "1.24.4-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "homepage": "https://buddy.works/docs/cli",