@gaia-ai/core 0.6.3 → 0.6.4
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/dist/src/core/logger.d.ts +18 -1
- package/dist/src/core/logger.js +35 -8
- package/package.json +1 -1
|
@@ -3,6 +3,14 @@ export type LogSink = {
|
|
|
3
3
|
} | {
|
|
4
4
|
kind: 'file';
|
|
5
5
|
path: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Tee: pretty stdout AND the durable `log.txt`. The DEFAULT on a TTY since
|
|
9
|
+
* GAIA-237 — see {@link resolveSink}.
|
|
10
|
+
*/
|
|
11
|
+
| {
|
|
12
|
+
kind: 'both';
|
|
13
|
+
path: string;
|
|
6
14
|
};
|
|
7
15
|
export interface ConductorLogger {
|
|
8
16
|
debug(obj: object, msg?: string): void;
|
|
@@ -12,7 +20,16 @@ export interface ConductorLogger {
|
|
|
12
20
|
}
|
|
13
21
|
/**
|
|
14
22
|
* Pick the log sink. Precedence: explicit CLI override (`sink`) > the
|
|
15
|
-
* GAIA_CONDUCTOR_LOG env var >
|
|
23
|
+
* GAIA_CONDUCTOR_LOG env var > default (`both` on a TTY, `file` otherwise).
|
|
24
|
+
*
|
|
25
|
+
* GAIA-237: the TTY default used to be stdout-ONLY, which made the conductor's
|
|
26
|
+
* own diagnostics non-durable exactly where it normally runs — inside a herdr
|
|
27
|
+
* pane, which IS a TTY. A well-formed `lifecycle hook failed` record (hook +
|
|
28
|
+
* worktree + ticket + err) was therefore written nowhere and died with the pane,
|
|
29
|
+
* so an aborting worktree bootstrap left no trace to find. The default now tees:
|
|
30
|
+
* the operator keeps pretty stdout AND the record lands in `log.txt`. An
|
|
31
|
+
* EXPLICIT `stdout` / `file` (CLI flag or GAIA_CONDUCTOR_LOG) keeps its exact
|
|
32
|
+
* previous meaning — one stream, chosen deliberately.
|
|
16
33
|
*/
|
|
17
34
|
export declare function resolveSink(env: NodeJS.ProcessEnv, isTTY: boolean, checkoutRoot: string, override?: string): LogSink;
|
|
18
35
|
/**
|
package/dist/src/core/logger.js
CHANGED
|
@@ -3,19 +3,27 @@ import pino from 'pino';
|
|
|
3
3
|
import pretty from 'pino-pretty';
|
|
4
4
|
/**
|
|
5
5
|
* Pick the log sink. Precedence: explicit CLI override (`sink`) > the
|
|
6
|
-
* GAIA_CONDUCTOR_LOG env var >
|
|
6
|
+
* GAIA_CONDUCTOR_LOG env var > default (`both` on a TTY, `file` otherwise).
|
|
7
|
+
*
|
|
8
|
+
* GAIA-237: the TTY default used to be stdout-ONLY, which made the conductor's
|
|
9
|
+
* own diagnostics non-durable exactly where it normally runs — inside a herdr
|
|
10
|
+
* pane, which IS a TTY. A well-formed `lifecycle hook failed` record (hook +
|
|
11
|
+
* worktree + ticket + err) was therefore written nowhere and died with the pane,
|
|
12
|
+
* so an aborting worktree bootstrap left no trace to find. The default now tees:
|
|
13
|
+
* the operator keeps pretty stdout AND the record lands in `log.txt`. An
|
|
14
|
+
* EXPLICIT `stdout` / `file` (CLI flag or GAIA_CONDUCTOR_LOG) keeps its exact
|
|
15
|
+
* previous meaning — one stream, chosen deliberately.
|
|
7
16
|
*/
|
|
8
17
|
export function resolveSink(env, isTTY, checkoutRoot, override) {
|
|
9
|
-
const
|
|
10
|
-
kind: 'file',
|
|
11
|
-
path: join(checkoutRoot, 'log.txt'),
|
|
12
|
-
};
|
|
18
|
+
const path = join(checkoutRoot, 'log.txt');
|
|
13
19
|
const choice = override ?? env.GAIA_CONDUCTOR_LOG;
|
|
14
20
|
if (choice === 'stdout')
|
|
15
21
|
return { kind: 'stdout' };
|
|
16
22
|
if (choice === 'file')
|
|
17
|
-
return
|
|
18
|
-
|
|
23
|
+
return { kind: 'file', path };
|
|
24
|
+
if (choice === 'both')
|
|
25
|
+
return { kind: 'both', path };
|
|
26
|
+
return isTTY ? { kind: 'both', path } : { kind: 'file', path };
|
|
19
27
|
}
|
|
20
28
|
/**
|
|
21
29
|
* Pick the log level. Precedence: explicit CLI override (`level`) >
|
|
@@ -32,5 +40,24 @@ export function createLogger(opts) {
|
|
|
32
40
|
if (sink.kind === 'stdout') {
|
|
33
41
|
return pino({ level }, pretty({ colorize: true, sync: true }));
|
|
34
42
|
}
|
|
35
|
-
|
|
43
|
+
const file = () => pino.destination({
|
|
44
|
+
dest: sink.path,
|
|
45
|
+
append: true,
|
|
46
|
+
mkdir: true,
|
|
47
|
+
sync: true,
|
|
48
|
+
});
|
|
49
|
+
if (sink.kind === 'file') {
|
|
50
|
+
return pino({ level }, file());
|
|
51
|
+
}
|
|
52
|
+
// 'both' — tee via multistream so the pane stays readable AND the record is
|
|
53
|
+
// durable (GAIA-237). `level` is enforced by the logger, so each stream takes
|
|
54
|
+
// everything that got through.
|
|
55
|
+
// multistream filters per stream and defaults each entry to `info`, which
|
|
56
|
+
// would silently drop `--log-level debug` from BOTH streams — so each entry
|
|
57
|
+
// carries the resolved level and the logger stays the single gate.
|
|
58
|
+
const at = level;
|
|
59
|
+
return pino({ level }, pino.multistream([
|
|
60
|
+
{ level: at, stream: pretty({ colorize: true, sync: true }) },
|
|
61
|
+
{ level: at, stream: file() },
|
|
62
|
+
]));
|
|
36
63
|
}
|
package/package.json
CHANGED