libretto 0.5.0 → 0.5.1
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/README.md +106 -36
- package/dist/cli/cli.js +22 -97
- package/dist/cli/commands/browser.js +86 -59
- package/dist/cli/commands/execution.js +199 -86
- package/dist/cli/commands/init.js +30 -8
- package/dist/cli/commands/logs.js +4 -5
- package/dist/cli/commands/shared.js +30 -29
- package/dist/cli/commands/snapshot.js +26 -39
- package/dist/cli/core/ai-config.js +9 -2
- package/dist/cli/core/api-snapshot-analyzer.js +15 -5
- package/dist/cli/core/browser.js +132 -29
- package/dist/cli/core/context.js +4 -1
- package/dist/cli/core/session-telemetry.js +5 -2
- package/dist/cli/core/session.js +21 -8
- package/dist/cli/core/snapshot-analyzer.js +14 -31
- package/dist/cli/core/snapshot-api-config.js +2 -6
- package/dist/cli/core/telemetry.js +10 -2
- package/dist/cli/framework/simple-cli.js +45 -25
- package/dist/cli/router.js +14 -21
- package/dist/cli/workers/run-integration-runtime.js +24 -5
- package/dist/cli/workers/run-integration-worker-protocol.js +3 -1
- package/dist/cli/workers/run-integration-worker.js +1 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.js +7 -10
- package/dist/runtime/download/download.js +5 -1
- package/dist/runtime/extract/extract.js +11 -2
- package/dist/runtime/network/network.js +8 -1
- package/dist/runtime/recovery/agent.js +6 -2
- package/dist/runtime/recovery/errors.js +3 -1
- package/dist/runtime/recovery/recovery.js +3 -1
- package/dist/shared/condense-dom/condense-dom.js +6 -13
- package/dist/shared/config/config.d.ts +1 -9
- package/dist/shared/config/config.js +0 -18
- package/dist/shared/config/index.d.ts +2 -1
- package/dist/shared/config/index.js +0 -10
- package/dist/shared/debug/pause.js +9 -3
- package/dist/shared/instrumentation/instrument.js +101 -5
- package/dist/shared/llm/ai-sdk-adapter.js +3 -1
- package/dist/shared/llm/client.js +3 -1
- package/dist/shared/logger/index.js +4 -1
- package/dist/shared/run/api.js +3 -1
- package/dist/shared/run/browser.js +7 -2
- package/dist/shared/state/session-state.d.ts +2 -1
- package/dist/shared/state/session-state.js +5 -2
- package/dist/shared/visualization/ghost-cursor.js +19 -10
- package/dist/shared/visualization/highlight.js +9 -6
- package/dist/shared/workflow/workflow.d.ts +4 -5
- package/dist/shared/workflow/workflow.js +3 -5
- package/package.json +6 -2
- package/scripts/check-skills-sync.mjs +25 -0
- package/scripts/compare-eval-summary.mjs +47 -0
- package/scripts/postinstall.mjs +15 -15
- package/scripts/prepare-release.sh +97 -0
- package/scripts/skills-libretto.mjs +103 -0
- package/scripts/summarize-evals.mjs +135 -0
- package/scripts/sync-skills.mjs +12 -0
- package/skills/libretto/SKILL.md +113 -49
- package/skills/libretto/references/code-generation-rules.md +208 -0
- package/skills/libretto/references/configuration-file-reference.md +53 -0
- package/skills/libretto/references/site-security-review.md +143 -0
- package/src/cli/cli.ts +23 -110
- package/src/cli/commands/browser.ts +94 -70
- package/src/cli/commands/execution.ts +233 -102
- package/src/cli/commands/init.ts +32 -9
- package/src/cli/commands/logs.ts +7 -7
- package/src/cli/commands/shared.ts +36 -37
- package/src/cli/commands/snapshot.ts +44 -59
- package/src/cli/core/ai-config.ts +12 -3
- package/src/cli/core/api-snapshot-analyzer.ts +17 -6
- package/src/cli/core/browser.ts +178 -41
- package/src/cli/core/context.ts +7 -2
- package/src/cli/core/session-telemetry.ts +19 -8
- package/src/cli/core/session.ts +21 -7
- package/src/cli/core/snapshot-analyzer.ts +26 -46
- package/src/cli/core/snapshot-api-config.ts +170 -175
- package/src/cli/core/telemetry.ts +16 -3
- package/src/cli/framework/simple-cli.ts +144 -77
- package/src/cli/router.ts +13 -21
- package/src/cli/workers/run-integration-runtime.ts +36 -9
- package/src/cli/workers/run-integration-worker-protocol.ts +2 -0
- package/src/cli/workers/run-integration-worker.ts +1 -4
- package/src/index.ts +73 -66
- package/src/runtime/download/download.ts +62 -58
- package/src/runtime/download/index.ts +5 -5
- package/src/runtime/extract/extract.ts +71 -61
- package/src/runtime/network/index.ts +3 -3
- package/src/runtime/network/network.ts +99 -93
- package/src/runtime/recovery/agent.ts +217 -212
- package/src/runtime/recovery/errors.ts +107 -104
- package/src/runtime/recovery/index.ts +3 -3
- package/src/runtime/recovery/recovery.ts +38 -35
- package/src/shared/condense-dom/condense-dom.ts +15 -18
- package/src/shared/config/config.ts +0 -19
- package/src/shared/config/index.ts +0 -5
- package/src/shared/debug/pause.ts +57 -51
- package/src/shared/instrumentation/errors.ts +64 -62
- package/src/shared/instrumentation/index.ts +5 -5
- package/src/shared/instrumentation/instrument.ts +339 -209
- package/src/shared/llm/ai-sdk-adapter.ts +58 -55
- package/src/shared/llm/client.ts +181 -174
- package/src/shared/llm/types.ts +39 -39
- package/src/shared/logger/index.ts +11 -4
- package/src/shared/logger/logger.ts +312 -306
- package/src/shared/logger/sinks.ts +118 -114
- package/src/shared/paths/paths.ts +50 -49
- package/src/shared/paths/repo-root.ts +17 -17
- package/src/shared/run/api.ts +5 -1
- package/src/shared/run/browser.ts +12 -3
- package/src/shared/state/index.ts +9 -9
- package/src/shared/state/session-state.ts +46 -43
- package/src/shared/visualization/ghost-cursor.ts +161 -148
- package/src/shared/visualization/highlight.ts +89 -86
- package/src/shared/visualization/index.ts +13 -13
- package/src/shared/workflow/workflow.ts +19 -25
- package/skills/libretto/references/reverse-engineering-network-requests.md +0 -39
- package/skills/libretto/references/user-action-log.md +0 -31
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
function generateId(): string {
|
|
2
|
-
|
|
2
|
+
return Math.random().toString(36).substring(2, 15);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export type LogOptions = {
|
|
6
|
-
|
|
6
|
+
timestamp?: Date;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -12,341 +12,347 @@ export type LogOptions = {
|
|
|
12
12
|
* implement withScope, withContext, flush, etc.
|
|
13
13
|
*/
|
|
14
14
|
export type MinimalLogger = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
info: (event: string, data?: any) => void;
|
|
16
|
+
warn: (event: string, data?: any) => void;
|
|
17
|
+
error: (event: string, data?: any) => any;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/** Default console logger used when callers omit the logger option. */
|
|
21
21
|
export const defaultLogger: MinimalLogger = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
info(event, data) {
|
|
23
|
+
console.log(`[INFO] ${event}`, data ?? "");
|
|
24
|
+
},
|
|
25
|
+
warn(event, data) {
|
|
26
|
+
console.warn(`[WARN] ${event}`, data ?? "");
|
|
27
|
+
},
|
|
28
|
+
error(event, data) {
|
|
29
|
+
console.error(`[ERROR] ${event}`, data ?? "");
|
|
30
|
+
},
|
|
25
31
|
};
|
|
26
32
|
|
|
27
33
|
export type LoggerApi = {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
34
|
+
log: (
|
|
35
|
+
event: string,
|
|
36
|
+
data?: Record<string, any>,
|
|
37
|
+
options?: LogOptions,
|
|
38
|
+
) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Logs an error and returns an Error object that can be thrown
|
|
41
|
+
*
|
|
42
|
+
* either pass in an Error directly as data or as { error: Error, ...other_data }
|
|
43
|
+
*/
|
|
44
|
+
error: (
|
|
45
|
+
event: string,
|
|
46
|
+
data?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
47
|
+
options?: LogOptions,
|
|
48
|
+
) => Error;
|
|
49
|
+
warn: (
|
|
50
|
+
event: string,
|
|
51
|
+
data?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
52
|
+
options?: LogOptions,
|
|
53
|
+
) => void;
|
|
54
|
+
info: (
|
|
55
|
+
event: string,
|
|
56
|
+
data?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
57
|
+
options?: LogOptions,
|
|
58
|
+
) => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Context passed in will be attached to all entries in this scope.
|
|
62
|
+
*/
|
|
63
|
+
withScope: (scope: string, context?: Record<string, any>) => LoggerApi;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Context passed in will be attached to all entries.
|
|
67
|
+
*/
|
|
68
|
+
withContext: (context: Record<string, any>) => LoggerApi;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Flushes all sinks in reverse order (most recently added first).
|
|
72
|
+
*/
|
|
73
|
+
flush: () => Promise<void>;
|
|
68
74
|
};
|
|
69
75
|
|
|
70
76
|
export type LoggerSink = {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
write: (args: {
|
|
78
|
+
id: string;
|
|
79
|
+
scope: string;
|
|
80
|
+
level: "log" | "error" | "warn" | "info";
|
|
81
|
+
event: string;
|
|
82
|
+
data: Record<string, any>;
|
|
83
|
+
options?: LogOptions;
|
|
84
|
+
}) => void;
|
|
85
|
+
flush?: () => Promise<void>;
|
|
86
|
+
close?: () => Promise<void>;
|
|
81
87
|
};
|
|
82
88
|
|
|
83
89
|
type SinkLifecycleState = {
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
closed: boolean;
|
|
91
|
+
closing?: Promise<void>;
|
|
86
92
|
};
|
|
87
93
|
|
|
88
94
|
const sinkLifecycleState = new WeakMap<LoggerSink, SinkLifecycleState>();
|
|
89
95
|
|
|
90
96
|
function getSinkLifecycleState(sink: LoggerSink): SinkLifecycleState {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const existingState = sinkLifecycleState.get(sink);
|
|
98
|
+
if (existingState) {
|
|
99
|
+
return existingState;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const initialState: SinkLifecycleState = { closed: false };
|
|
103
|
+
sinkLifecycleState.set(sink, initialState);
|
|
104
|
+
return initialState;
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
function isSinkClosedOrClosing(sink: LoggerSink): boolean {
|
|
102
|
-
|
|
103
|
-
|
|
108
|
+
const state = sinkLifecycleState.get(sink);
|
|
109
|
+
return Boolean(state?.closed || state?.closing);
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
async function closeSinkOnce(sink: LoggerSink): Promise<void> {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
113
|
+
if (!sink.close) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const state = getSinkLifecycleState(sink);
|
|
118
|
+
if (state.closed) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (state.closing) {
|
|
123
|
+
return state.closing;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
state.closing = (async () => {
|
|
127
|
+
try {
|
|
128
|
+
await sink.close?.();
|
|
129
|
+
} catch {
|
|
130
|
+
// Ignore close errors - we're likely shutting down
|
|
131
|
+
} finally {
|
|
132
|
+
state.closed = true;
|
|
133
|
+
state.closing = undefined;
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
|
|
137
|
+
return state.closing;
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
function isObject(value: unknown): value is Record<string, unknown> {
|
|
135
|
-
|
|
141
|
+
return typeof value === "object" && value !== null;
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
function removeUndefined(data: any): any {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
if (typeof data === "object" && data !== null) {
|
|
146
|
+
return Object.fromEntries(
|
|
147
|
+
Object.entries(data).filter(([_, value]) => value !== undefined),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return data;
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
export class Logger implements LoggerApi {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
154
|
+
private readonly prefix: string;
|
|
155
|
+
|
|
156
|
+
constructor(
|
|
157
|
+
private readonly scopes: string[] = [],
|
|
158
|
+
private readonly sinks: LoggerSink[] = [],
|
|
159
|
+
private readonly scopeData: Record<string, any> = {},
|
|
160
|
+
) {
|
|
161
|
+
this.prefix = scopes.join(".");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
entry(entry: {
|
|
165
|
+
level: "log" | "error" | "warn" | "info";
|
|
166
|
+
event: string;
|
|
167
|
+
data?: Record<string, any>;
|
|
168
|
+
options?: LogOptions;
|
|
169
|
+
}) {
|
|
170
|
+
this.sinks.forEach((sink) => {
|
|
171
|
+
if (isSinkClosedOrClosing(sink)) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
sink.write({
|
|
176
|
+
id: generateId(),
|
|
177
|
+
scope: this.prefix,
|
|
178
|
+
level: entry.level,
|
|
179
|
+
event: entry.event,
|
|
180
|
+
data: removeUndefined({ ...this.scopeData, ...entry.data }),
|
|
181
|
+
options: entry.options,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
log(event: string, data?: Record<string, any>, options?: LogOptions) {
|
|
187
|
+
this.entry({ level: "log", event, data, options });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
error(
|
|
191
|
+
event: string,
|
|
192
|
+
dataOrError?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
193
|
+
options?: LogOptions,
|
|
194
|
+
) {
|
|
195
|
+
const data =
|
|
196
|
+
dataOrError instanceof Error
|
|
197
|
+
? {
|
|
198
|
+
error: {
|
|
199
|
+
type: dataOrError.constructor.name,
|
|
200
|
+
message: dataOrError.message,
|
|
201
|
+
stack: dataOrError.stack || null,
|
|
202
|
+
},
|
|
203
|
+
}
|
|
204
|
+
: isObject(dataOrError) && dataOrError.error instanceof Error
|
|
205
|
+
? {
|
|
206
|
+
...dataOrError,
|
|
207
|
+
error: {
|
|
208
|
+
type: dataOrError.error.constructor.name,
|
|
209
|
+
message: dataOrError.error.message,
|
|
210
|
+
stack: dataOrError.error.stack || null,
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
: isObject(dataOrError)
|
|
214
|
+
? dataOrError
|
|
215
|
+
: dataOrError !== undefined
|
|
216
|
+
? { error: dataOrError }
|
|
217
|
+
: undefined;
|
|
218
|
+
|
|
219
|
+
this.entry({
|
|
220
|
+
level: "error",
|
|
221
|
+
event,
|
|
222
|
+
data: data as Error | Record<string, any>,
|
|
223
|
+
options,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (dataOrError instanceof Error) {
|
|
227
|
+
return dataOrError;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (isObject(dataOrError) && dataOrError.error instanceof Error) {
|
|
231
|
+
return dataOrError.error;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let message = event;
|
|
235
|
+
if (data !== undefined) {
|
|
236
|
+
try {
|
|
237
|
+
message += "\n" + JSON.stringify(data, undefined, 2);
|
|
238
|
+
} catch {
|
|
239
|
+
message += "\n[Unserializable error data]";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return new Error(message);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
warn(
|
|
246
|
+
event: string,
|
|
247
|
+
dataOrError?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
248
|
+
options?: LogOptions,
|
|
249
|
+
) {
|
|
250
|
+
const data =
|
|
251
|
+
dataOrError instanceof Error
|
|
252
|
+
? {
|
|
253
|
+
error: {
|
|
254
|
+
type: dataOrError.constructor.name,
|
|
255
|
+
message: dataOrError.message,
|
|
256
|
+
stack: dataOrError.stack || null,
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
: isObject(dataOrError) && dataOrError.error instanceof Error
|
|
260
|
+
? {
|
|
261
|
+
...dataOrError,
|
|
262
|
+
error: {
|
|
263
|
+
type: dataOrError.error.constructor.name,
|
|
264
|
+
message: dataOrError.error.message,
|
|
265
|
+
stack: dataOrError.error.stack || null,
|
|
266
|
+
},
|
|
267
|
+
}
|
|
268
|
+
: isObject(dataOrError)
|
|
269
|
+
? dataOrError
|
|
270
|
+
: dataOrError !== undefined
|
|
271
|
+
? { error: dataOrError }
|
|
272
|
+
: undefined;
|
|
273
|
+
|
|
274
|
+
this.entry({
|
|
275
|
+
level: "warn",
|
|
276
|
+
event,
|
|
277
|
+
data: data as Record<string, any>,
|
|
278
|
+
options,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
info(
|
|
283
|
+
event: string,
|
|
284
|
+
dataOrError?: Error | ({ error: Error } & Record<string, any>) | unknown,
|
|
285
|
+
options?: LogOptions,
|
|
286
|
+
) {
|
|
287
|
+
const data =
|
|
288
|
+
dataOrError instanceof Error
|
|
289
|
+
? {
|
|
290
|
+
error: {
|
|
291
|
+
type: dataOrError.constructor.name,
|
|
292
|
+
message: dataOrError.message,
|
|
293
|
+
stack: dataOrError.stack || null,
|
|
294
|
+
},
|
|
295
|
+
}
|
|
296
|
+
: isObject(dataOrError) && dataOrError.error instanceof Error
|
|
297
|
+
? {
|
|
298
|
+
...dataOrError,
|
|
299
|
+
error: {
|
|
300
|
+
type: dataOrError.error.constructor.name,
|
|
301
|
+
message: dataOrError.error.message,
|
|
302
|
+
stack: dataOrError.error.stack || null,
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
: isObject(dataOrError)
|
|
306
|
+
? dataOrError
|
|
307
|
+
: dataOrError !== undefined
|
|
308
|
+
? { error: dataOrError }
|
|
309
|
+
: undefined;
|
|
310
|
+
|
|
311
|
+
this.entry({
|
|
312
|
+
level: "info",
|
|
313
|
+
event,
|
|
314
|
+
data: data as Record<string, any>,
|
|
315
|
+
options,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
withScope(scope: string, context: Record<string, any> = {}): LoggerApi {
|
|
320
|
+
return new Logger([...this.scopes, scope], this.sinks, {
|
|
321
|
+
...this.scopeData,
|
|
322
|
+
...context,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
withContext(context: Record<string, any>): LoggerApi {
|
|
327
|
+
return new Logger(this.scopes, this.sinks, {
|
|
328
|
+
...this.scopeData,
|
|
329
|
+
...context,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
withSink(sink: LoggerSink): Logger {
|
|
334
|
+
return new Logger(this.scopes, [...this.sinks, sink]);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
async flush(): Promise<void> {
|
|
338
|
+
for (let i = this.sinks.length - 1; i >= 0; i--) {
|
|
339
|
+
const sink = this.sinks[i];
|
|
340
|
+
if (!sink) continue;
|
|
341
|
+
if (isSinkClosedOrClosing(sink)) continue;
|
|
342
|
+
try {
|
|
343
|
+
await sink.flush?.();
|
|
344
|
+
} catch {
|
|
345
|
+
// Ignore flush errors - we're likely shutting down
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async close(): Promise<void> {
|
|
351
|
+
await this.flush();
|
|
352
|
+
for (let i = this.sinks.length - 1; i >= 0; i--) {
|
|
353
|
+
const sink = this.sinks[i];
|
|
354
|
+
if (!sink) continue;
|
|
355
|
+
await closeSinkOnce(sink);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
352
358
|
}
|