@gaunt-sloth/core 2.0.0-alpha.23 → 2.0.0-alpha.25
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 +43 -18
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/defaults.d.ts +6 -7
- package/dist/config/defaults.js +4 -8
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/loader.d.ts +50 -3
- package/dist/config/loader.js +345 -29
- package/dist/config/loader.js.map +1 -1
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/schema.d.ts +2441 -116
- package/dist/config/schema.js +930 -19
- package/dist/config/schema.js.map +1 -1
- package/dist/config/shell-policy.d.ts +466 -116
- package/dist/config/shell-policy.js +273 -62
- package/dist/config/shell-policy.js.map +1 -1
- package/dist/config/tool-descriptions.d.ts +165 -0
- package/dist/config/tool-descriptions.js +229 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +139 -6
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +85 -2
- package/dist/core/GthAbstractAgent.js +194 -1
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +341 -58
- package/dist/core/GthAgentRunner.js +857 -149
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +99 -0
- package/dist/core/GthLangChainAgent.js +388 -3
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +16 -0
- package/dist/core/debugCapture.js.map +1 -1
- package/dist/core/launchBanner.d.ts +120 -0
- package/dist/core/launchBanner.js +399 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/plainToolIndication.js +61 -35
- package/dist/core/plainToolIndication.js.map +1 -1
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +129 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +75 -0
- package/dist/core/shell/approvalStop.js +108 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +41 -1
- package/dist/core/shell/normalize.js +58 -4
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +138 -0
- package/dist/core/shell/openWorld.js +523 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +560 -0
- package/dist/core/shell/rater.js +895 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +66 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +14 -1
- package/dist/core/toolDisplay.js +69 -12
- package/dist/core/toolDisplay.js.map +1 -1
- package/dist/core/toolOutputChannel.d.ts +33 -6
- package/dist/core/toolOutputChannel.js +61 -8
- package/dist/core/toolOutputChannel.js.map +1 -1
- package/dist/core/types.d.ts +71 -9
- package/dist/core/types.js.map +1 -1
- package/dist/providers/geminiSchemaSanitizer.d.ts +6 -3
- package/dist/providers/geminiSchemaSanitizer.js +152 -6
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -1
- package/dist/providers/modelDiscovery.d.ts +18 -4
- package/dist/providers/modelDiscovery.js +67 -17
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/openai.js +34 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +8 -7
- package/dist/runtime/askStructured.js +8 -7
- package/dist/runtime/askStructured.js.map +1 -1
- package/dist/runtime/conversation.js +89 -76
- package/dist/runtime/conversation.js.map +1 -1
- package/dist/runtime/singleShot.js +71 -60
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +30 -0
- package/dist/utils/consoleUtils.js +27 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +58 -0
- package/dist/utils/debugDump.js +149 -15
- package/dist/utils/debugDump.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +22 -8
- package/dist/utils/llmUtils.js +48 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.js +68 -20
- package/dist/utils/redactSecrets.js.map +1 -1
- package/dist/utils/systemUtils.d.ts +17 -0
- package/dist/utils/systemUtils.js +17 -0
- package/dist/utils/systemUtils.js.map +1 -1
- package/package.json +5 -2
- package/schema/gsloth-config.schema.json +1484 -466
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../src/runtime/conversation.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAkB1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,SAAiB,EACjB,YAAsB,EACtB,MAAiB,EACjB,SAA0B,EAC1B,OAAO,GAAe,KAAK,EAC3B,YAA8B;IAE9B,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../src/runtime/conversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,70 +40,81 @@ export async function runSingleShot(source,
|
|
|
40
40
|
// The agent's composed prompt is a superset of this preamble, so dropping it is content-preserving.
|
|
41
41
|
_preamble, content, config, resolvers, command = 'ask', agentFactory) {
|
|
42
42
|
const progressIndicator = config.streamOutput ? undefined : new ProgressIndicator('Thinking.');
|
|
43
|
-
// Only the human turn: the agent supplies the system prompt via `createAgent({ systemPrompt })`.
|
|
44
|
-
const messages = [new HumanMessage(content)];
|
|
45
|
-
// Resolve output path and initialize session logging if enabled
|
|
46
|
-
const filePath = getCommandOutputFilePath(config, source);
|
|
47
|
-
if (filePath) {
|
|
48
|
-
initSessionLogging(filePath, config.streamSessionInferenceLog);
|
|
49
|
-
}
|
|
50
|
-
// Run via Agent Runner (consistent with interactive session)
|
|
51
|
-
const runner = new GthAgentRunner(defaultStatusCallback, resolvers, agentFactory);
|
|
52
|
-
let succeeded = true;
|
|
53
|
-
let responseText = '';
|
|
54
|
-
const startedAt = Date.now();
|
|
55
43
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
project: getProjectDir(),
|
|
84
|
-
model: config.modelDisplayName,
|
|
85
|
-
prompt: content,
|
|
86
|
-
response: responseText,
|
|
87
|
-
tokensInput: runStats.tokensInput,
|
|
88
|
-
tokensOutput: runStats.tokensOutput,
|
|
89
|
-
tools: runStats.tools.length > 0 ? runStats.tools : undefined,
|
|
90
|
-
durationMs: Date.now() - startedAt,
|
|
91
|
-
});
|
|
92
|
-
progressIndicator?.stop();
|
|
93
|
-
if (config.writeOutputToFile === false) {
|
|
94
|
-
display('\n'); // something going on in some terminals, they swallow last line of output
|
|
95
|
-
}
|
|
96
|
-
if (filePath) {
|
|
44
|
+
// Only the human turn: the agent supplies the system prompt via `createAgent({ systemPrompt })`.
|
|
45
|
+
const messages = [new HumanMessage(content)];
|
|
46
|
+
// Resolve output path and initialize session logging if enabled
|
|
47
|
+
const filePath = getCommandOutputFilePath(config, source);
|
|
48
|
+
if (filePath) {
|
|
49
|
+
initSessionLogging(filePath, config.streamSessionInferenceLog);
|
|
50
|
+
}
|
|
51
|
+
// Run via Agent Runner (consistent with interactive session)
|
|
52
|
+
const runner = new GthAgentRunner(defaultStatusCallback, resolvers, agentFactory);
|
|
53
|
+
let succeeded = true;
|
|
54
|
+
let responseText = '';
|
|
55
|
+
const startedAt = Date.now();
|
|
56
|
+
try {
|
|
57
|
+
await runner.init(command, config, new MemorySaver());
|
|
58
|
+
responseText = await runner.processMessages(messages);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
succeeded = false;
|
|
62
|
+
displayError(`Failed to get answer: ${err instanceof Error ? err.message : String(err)}`);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await runner.cleanup();
|
|
66
|
+
}
|
|
67
|
+
// GS2-16: live token usage + invoked tool names for this run (fail-soft; empty when the
|
|
68
|
+
// provider reported no usage / the runner has no stats). Read post-cleanup — the runner
|
|
69
|
+
// snapshots stats at cleanup() so this still reflects the finished run.
|
|
70
|
+
let runStats = { tools: [] };
|
|
97
71
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
72
|
+
const s = runner.getRunStats?.();
|
|
73
|
+
if (s)
|
|
74
|
+
runStats = s;
|
|
101
75
|
}
|
|
102
|
-
catch
|
|
103
|
-
|
|
104
|
-
displayError(error instanceof Error ? error.message : String(error));
|
|
76
|
+
catch {
|
|
77
|
+
/* fail-soft: analytics must never affect this run */
|
|
105
78
|
}
|
|
79
|
+
// GS2-7 (B20): opt-in, fail-soft session history. A no-op unless `history.enabled`; never throws
|
|
80
|
+
// (recordSessionSafe is fully guarded) so a DB problem can't abort or alter this run.
|
|
81
|
+
// GS2-16 threads token/tool analytics; costUsd is intentionally left unset (no reliable price).
|
|
82
|
+
recordSessionSafe(config, {
|
|
83
|
+
command,
|
|
84
|
+
project: getProjectDir(),
|
|
85
|
+
model: config.modelDisplayName,
|
|
86
|
+
prompt: content,
|
|
87
|
+
response: responseText,
|
|
88
|
+
tokensInput: runStats.tokensInput,
|
|
89
|
+
tokensOutput: runStats.tokensOutput,
|
|
90
|
+
tools: runStats.tools.length > 0 ? runStats.tools : undefined,
|
|
91
|
+
durationMs: Date.now() - startedAt,
|
|
92
|
+
});
|
|
93
|
+
progressIndicator?.stop();
|
|
94
|
+
if (config.writeOutputToFile === false) {
|
|
95
|
+
display('\n'); // something going on in some terminals, they swallow last line of output
|
|
96
|
+
}
|
|
97
|
+
if (filePath) {
|
|
98
|
+
try {
|
|
99
|
+
flushSessionLog();
|
|
100
|
+
stopSessionLogging();
|
|
101
|
+
displaySuccess(`\n\nThis report can be found in ${filePath}`);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
displayError(`Failed to write answer to file: ${filePath}`);
|
|
105
|
+
displayError(error instanceof Error ? error.message : String(error));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { ok: succeeded, answer: responseText, ...runStats };
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
// EXT-53: the indicator owns a 1s setInterval — an active libuv handle that keeps Node's event
|
|
112
|
+
// loop from ever draining, so leaking it hangs the CLI forever after the work is done. The
|
|
113
|
+
// `stop()` above sits where it does for output ordering (before the trailing newline / the
|
|
114
|
+
// "report can be found in …" line); this `finally` guarantees the handle is also released when
|
|
115
|
+
// anything above throws — notably `runner.cleanup()`, which is outside the inner catch.
|
|
116
|
+
// `stop()` is idempotent, so the normal path's second call is a no-op.
|
|
117
|
+
progressIndicator?.stop();
|
|
106
118
|
}
|
|
107
|
-
return { ok: succeeded, answer: responseText, ...runStats };
|
|
108
119
|
}
|
|
109
120
|
//# sourceMappingURL=singleShot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleShot.js","sourceRoot":"","sources":["../../src/runtime/singleShot.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAe1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc;AACd,2FAA2F;AAC3F,gGAAgG;AAChG,iGAAiG;AACjG,iGAAiG;AACjG,mGAAmG;AACnG,2FAA2F;AAC3F,iGAAiG;AACjG,gGAAgG;AAChG,oGAAoG;AACpG,SAAiB,EACjB,OAAe,EACf,MAAiB,EACjB,SAA0B,EAC1B,OAAO,GAAe,KAAK,EAC3B,YAA8B;IAE9B,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/F,iGAAiG;
|
|
1
|
+
{"version":3,"file":"singleShot.js","sourceRoot":"","sources":["../../src/runtime/singleShot.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A dot-per-second terminal progress indicator.
|
|
3
|
+
*
|
|
4
|
+
* **EXT-53 — always stop it, on every exit path.** In its automatic (non-`manual`) mode the
|
|
5
|
+
* indicator owns a 1s `setInterval`, which is an *active libuv handle*: while it is alive Node's
|
|
6
|
+
* event loop can never drain and the process cannot exit, no matter that every await has resolved.
|
|
7
|
+
* A `stop()` that is only reachable on the success path therefore turns any error into a hang
|
|
8
|
+
* rather than an exit. Construct the indicator OUTSIDE the `try` and clear it in a `finally`.
|
|
9
|
+
*
|
|
10
|
+
* `stop()` is idempotent (see below), so a `finally { indicator.stop() }` is always safe to add
|
|
11
|
+
* even where a success-path `stop()` already ran.
|
|
12
|
+
*/
|
|
1
13
|
export declare class ProgressIndicator {
|
|
2
14
|
private interval;
|
|
15
|
+
private readonly manual;
|
|
16
|
+
private stopped;
|
|
3
17
|
constructor(initialMessage: string, manual?: boolean);
|
|
4
18
|
private indicateInner;
|
|
5
19
|
indicate(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Clear the interval (releasing the libuv handle) and terminate the dot line with a newline.
|
|
22
|
+
*
|
|
23
|
+
* Idempotent: the handle is nulled and a second call is a complete no-op, so it emits no stray
|
|
24
|
+
* blank line. That is what makes it safe to call from a `finally` on top of an existing
|
|
25
|
+
* success-path `stop()`.
|
|
26
|
+
*/
|
|
6
27
|
stop(): void;
|
|
7
28
|
}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { stdout } from '#src/utils/systemUtils.js';
|
|
2
|
+
/**
|
|
3
|
+
* A dot-per-second terminal progress indicator.
|
|
4
|
+
*
|
|
5
|
+
* **EXT-53 — always stop it, on every exit path.** In its automatic (non-`manual`) mode the
|
|
6
|
+
* indicator owns a 1s `setInterval`, which is an *active libuv handle*: while it is alive Node's
|
|
7
|
+
* event loop can never drain and the process cannot exit, no matter that every await has resolved.
|
|
8
|
+
* A `stop()` that is only reachable on the success path therefore turns any error into a hang
|
|
9
|
+
* rather than an exit. Construct the indicator OUTSIDE the `try` and clear it in a `finally`.
|
|
10
|
+
*
|
|
11
|
+
* `stop()` is idempotent (see below), so a `finally { indicator.stop() }` is always safe to add
|
|
12
|
+
* even where a success-path `stop()` already ran.
|
|
13
|
+
*/
|
|
2
14
|
export class ProgressIndicator {
|
|
3
15
|
interval = undefined;
|
|
16
|
+
manual;
|
|
17
|
+
stopped = false;
|
|
4
18
|
constructor(initialMessage, manual) {
|
|
19
|
+
this.manual = !!manual;
|
|
5
20
|
stdout.write(initialMessage);
|
|
6
|
-
if (!manual) {
|
|
21
|
+
if (!this.manual) {
|
|
7
22
|
this.interval = setInterval(this.indicateInner, 1000);
|
|
8
23
|
}
|
|
9
24
|
}
|
|
@@ -11,14 +26,26 @@ export class ProgressIndicator {
|
|
|
11
26
|
stdout.write('.');
|
|
12
27
|
}
|
|
13
28
|
indicate() {
|
|
14
|
-
if (this.
|
|
29
|
+
if (!this.manual) {
|
|
15
30
|
throw new Error('ProgressIndicator.indicate only to be called in manual mode');
|
|
16
31
|
}
|
|
17
32
|
this.indicateInner();
|
|
18
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Clear the interval (releasing the libuv handle) and terminate the dot line with a newline.
|
|
36
|
+
*
|
|
37
|
+
* Idempotent: the handle is nulled and a second call is a complete no-op, so it emits no stray
|
|
38
|
+
* blank line. That is what makes it safe to call from a `finally` on top of an existing
|
|
39
|
+
* success-path `stop()`.
|
|
40
|
+
*/
|
|
19
41
|
stop() {
|
|
20
|
-
if (this.
|
|
42
|
+
if (this.stopped) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.stopped = true;
|
|
46
|
+
if (this.interval !== undefined) {
|
|
21
47
|
clearInterval(this.interval);
|
|
48
|
+
this.interval = undefined;
|
|
22
49
|
}
|
|
23
50
|
stdout.write('\n');
|
|
24
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProgressIndicator.js","sourceRoot":"","sources":["../../src/utils/ProgressIndicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD,MAAM,OAAO,iBAAiB;IACpB,QAAQ,GAAuB,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ProgressIndicator.js","sourceRoot":"","sources":["../../src/utils/ProgressIndicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,GAAuB,SAAS,CAAC;IAChC,MAAM,CAAU;IACzB,OAAO,GAAG,KAAK,CAAC;IAExB,YAAY,cAAsB,EAAE,MAAgB;QAClD,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAsB,CAAC;QAC7E,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED;;;;;;OAMG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
import { StatusLevel, StatusUpdateCallback } from '#src/core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* ANSI color codes — the 16-colour slots only, deliberately. A 16-colour slot is rendered with the
|
|
4
|
+
* user's OWN terminal theme colour, so output looks native in light and dark schemes alike; a
|
|
5
|
+
* 256-colour or 24-bit escape would pin us to one palette and clash with half of them.
|
|
6
|
+
*
|
|
7
|
+
* Exported so the surfaces that build their own pre-styled blocks (rather than passing a whole
|
|
8
|
+
* message through {@link colorText}) still draw from this one table — see
|
|
9
|
+
* `core/launchBanner.ts`, which paints only the face half of each banner row.
|
|
10
|
+
*
|
|
11
|
+
* `as const` because `packages/core` publishes `"./*.js": "./dist/*.js"`, so this is PUBLIC API of a
|
|
12
|
+
* published package: without it any consumer could assign `ANSI_COLORS.magenta` and repaint the
|
|
13
|
+
* whole CLI from the outside. Read-only, one table, no remote control.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ANSI_COLORS: {
|
|
16
|
+
readonly red: '\u001B[31m';
|
|
17
|
+
readonly yellow: '\u001B[33m';
|
|
18
|
+
readonly green: '\u001B[32m';
|
|
19
|
+
readonly magenta: '\u001B[35m';
|
|
20
|
+
readonly dim: '\u001B[2m';
|
|
21
|
+
readonly reset: '\u001B[0m';
|
|
22
|
+
};
|
|
2
23
|
export declare const initSessionLogging: (logFileName: string, enableLogging: boolean) => void;
|
|
3
24
|
/**
|
|
4
25
|
* Set the console logging level.
|
|
@@ -44,6 +65,15 @@ export declare function display(message: string): void;
|
|
|
44
65
|
* inner resets. The session log gets the ANSI-stripped text via {@link writeToSessionLog}.
|
|
45
66
|
*/
|
|
46
67
|
export declare function displayToolIndication(message: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* TUI-C33 — print the interactive-launch banner (the pre-styled block built by
|
|
70
|
+
* `core/launchBanner.ts`) on the plain surface. Same DISPLAY-level gate and stdout channel as
|
|
71
|
+
* {@link display}, so a quieted console silences it too, but deliberately NOT routed through
|
|
72
|
+
* {@link writeToSessionLog}: the session log is a transcript of the conversation, not a screenshot
|
|
73
|
+
* of the screen, and a five-row sloth at the top of it is noise. The block also styles itself (the
|
|
74
|
+
* face half of each row carries the colour), so no outer wrap is applied.
|
|
75
|
+
*/
|
|
76
|
+
export declare function displayLaunchBanner(message: string): void;
|
|
47
77
|
export declare function formatInputPrompt(message: string): string;
|
|
48
78
|
/**
|
|
49
79
|
* Display a debug message to the console and log it.
|
|
@@ -9,8 +9,20 @@ const loggingState = {
|
|
|
9
9
|
const consoleLevelState = {
|
|
10
10
|
currentLevel: StatusLevel.INFO, // Default to INFO level, not debug
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* ANSI color codes — the 16-colour slots only, deliberately. A 16-colour slot is rendered with the
|
|
14
|
+
* user's OWN terminal theme colour, so output looks native in light and dark schemes alike; a
|
|
15
|
+
* 256-colour or 24-bit escape would pin us to one palette and clash with half of them.
|
|
16
|
+
*
|
|
17
|
+
* Exported so the surfaces that build their own pre-styled blocks (rather than passing a whole
|
|
18
|
+
* message through {@link colorText}) still draw from this one table — see
|
|
19
|
+
* `core/launchBanner.ts`, which paints only the face half of each banner row.
|
|
20
|
+
*
|
|
21
|
+
* `as const` because `packages/core` publishes `"./*.js": "./dist/*.js"`, so this is PUBLIC API of a
|
|
22
|
+
* published package: without it any consumer could assign `ANSI_COLORS.magenta` and repaint the
|
|
23
|
+
* whole CLI from the outside. Read-only, one table, no remote control.
|
|
24
|
+
*/
|
|
25
|
+
export const ANSI_COLORS = {
|
|
14
26
|
red: '\x1b[31m',
|
|
15
27
|
yellow: '\x1b[33m',
|
|
16
28
|
green: '\x1b[32m',
|
|
@@ -159,6 +171,19 @@ export function displayToolIndication(message) {
|
|
|
159
171
|
writeToSessionLog(message + '\n');
|
|
160
172
|
su.info(message);
|
|
161
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* TUI-C33 — print the interactive-launch banner (the pre-styled block built by
|
|
176
|
+
* `core/launchBanner.ts`) on the plain surface. Same DISPLAY-level gate and stdout channel as
|
|
177
|
+
* {@link display}, so a quieted console silences it too, but deliberately NOT routed through
|
|
178
|
+
* {@link writeToSessionLog}: the session log is a transcript of the conversation, not a screenshot
|
|
179
|
+
* of the screen, and a five-row sloth at the top of it is noise. The block also styles itself (the
|
|
180
|
+
* face half of each row carries the colour), so no outer wrap is applied.
|
|
181
|
+
*/
|
|
182
|
+
export function displayLaunchBanner(message) {
|
|
183
|
+
if (!shouldDisplayLevel(StatusLevel.DISPLAY))
|
|
184
|
+
return;
|
|
185
|
+
su.log(message);
|
|
186
|
+
}
|
|
162
187
|
export function formatInputPrompt(message) {
|
|
163
188
|
return colorText(message, 'magenta');
|
|
164
189
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consoleUtils.js","sourceRoot":"","sources":["../../src/utils/consoleUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAapD,MAAM,YAAY,GAAiB;IACjC,cAAc,EAAE,SAAS;IACzB,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,iBAAiB,GAAsB;IAC3C,YAAY,EAAE,WAAW,CAAC,IAAI,EAAE,mCAAmC;CACpE,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"consoleUtils.js","sourceRoot":"","sources":["../../src/utils/consoleUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* GS2-48 — a process-level crash handler that writes an unattended, GS2-47-redacted debug snapshot
|
|
4
|
+
* when the process DIES, then exits — the counterpart to GS2-46's `/debug-dump`, which only helps
|
|
5
|
+
* while the process is alive to run the slash command. Most real failures are the process dying, at
|
|
6
|
+
* which point a slash command can't help, so this fires unconditionally, regardless of whether
|
|
7
|
+
* `debugLog` was ever turned on for the session (the snapshot draws on the always-on in-memory
|
|
8
|
+
* ring buffer — see {@link file://./debugUtils.ts}).
|
|
9
|
+
*
|
|
10
|
+
* SCOPE (deliberate): only `uncaughtException` and `unhandledRejection` are handled. Fatal SIGNALS
|
|
11
|
+
* are intentionally left to a follow-up — `SIGINT`/`SIGTERM` are already GRACEFUL-exit paths
|
|
12
|
+
* ({@link file://./systemUtils.ts} closes the log stream and exits 0), the TUI owns raw-mode Ctrl-C,
|
|
13
|
+
* and dumping a crash file on every Ctrl-C would be noise, not signal. Adding signal capture without
|
|
14
|
+
* fighting those handlers is a separate, careful piece of work.
|
|
15
|
+
*
|
|
16
|
+
* Exiting on these two events is NOT a behavioural regression: Node's default for an unhandled
|
|
17
|
+
* rejection is already to throw (terminate), and its default for an uncaught exception is to print
|
|
18
|
+
* the error and exit(1). This handler replicates that terminal behaviour (it still prints the
|
|
19
|
+
* ORIGINAL error) and only ADDS the snapshot — an uncaughtException LISTENER suppresses Node's own
|
|
20
|
+
* auto-print, which is exactly why the handler prints the error itself.
|
|
21
|
+
*
|
|
22
|
+
* CRASH-SAFETY invariants (the whole point of the node):
|
|
23
|
+
* - The handler is fully SYNCHRONOUS — no `async`/`await`, returns no promise. An async handler that
|
|
24
|
+
* rejected would raise a fresh `unhandledRejection` and re-enter, the exact loop the brief forbids.
|
|
25
|
+
* - A module-level {@link handling} guard is set BEFORE any work, so a throw anywhere inside cannot
|
|
26
|
+
* re-enter the handler and loop; a genuine re-entry short-circuits straight to exit.
|
|
27
|
+
* - Snapshotting is wrapped in try/catch; if it fails, the handler DEGRADES to printing the original
|
|
28
|
+
* error plus a one-line "failed to write crash snapshot" reason and still exits — it never masks
|
|
29
|
+
* the original error and never re-enters.
|
|
30
|
+
* - stderr is written with `fs.writeSync(2, …)`, NOT the async `consoleUtils`/`systemUtils` stream:
|
|
31
|
+
* `process.exit()` truncates pending async pipe writes, so the printed snapshot path (asserted by
|
|
32
|
+
* the e2e over a pipe) could be lost. This is a conscious, documented deviation from the
|
|
33
|
+
* "use consoleUtils for output" rule — that path is unsafe at crash time.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Session-supplied context folded into the snapshot when a crash fires. All optional: a crash before
|
|
37
|
+
* a session registers anything still produces a useful snapshot (error + stack + debugLog buffer +
|
|
38
|
+
* env), just without config/transcript.
|
|
39
|
+
*/
|
|
40
|
+
export interface CrashContext {
|
|
41
|
+
/** The effective resolved config. */
|
|
42
|
+
config?: unknown;
|
|
43
|
+
/** Model display name. */
|
|
44
|
+
modelDisplayName?: string;
|
|
45
|
+
/** The in-flight turn's transcript tail. */
|
|
46
|
+
transcriptTail?: unknown;
|
|
47
|
+
}
|
|
48
|
+
/** Replace the crash context wholesale. */
|
|
49
|
+
export declare function setCrashContext(ctx: CrashContext): void;
|
|
50
|
+
/**
|
|
51
|
+
* Merge a partial update into the crash context. The running agent calls this as it learns things
|
|
52
|
+
* (config at init, transcript tail before each turn) so a crash mid-run captures the latest state.
|
|
53
|
+
*/
|
|
54
|
+
export declare function updateCrashContext(patch: Partial<CrashContext>): void;
|
|
55
|
+
/** Clear the crash context (e.g. when a session ends). */
|
|
56
|
+
export declare function clearCrashContext(): void;
|
|
57
|
+
/** Read the current crash context (used as the default context source by the installed handler). */
|
|
58
|
+
export declare function getCrashContext(): CrashContext;
|
|
59
|
+
/**
|
|
60
|
+
* The crash-handling body. Exported (rather than only closed over by the listeners) so it can be
|
|
61
|
+
* unit-tested directly with an injected `exit` and `getContext`, without registering real process
|
|
62
|
+
* listeners or killing the test runner.
|
|
63
|
+
*
|
|
64
|
+
* @param error the thrown value / rejection reason
|
|
65
|
+
* @param origin `'uncaughtException'` | `'unhandledRejection'`
|
|
66
|
+
* @param exit terminator (default {@link process.exit}); injectable so tests capture the code
|
|
67
|
+
* @param getContext source of the snapshot context (default the module context)
|
|
68
|
+
*/
|
|
69
|
+
export declare function handleCrash(error: unknown, origin: string, exit?: (code: number) => void, getContext?: () => CrashContext): void;
|
|
70
|
+
/** Options for {@link installCrashHandler}. */
|
|
71
|
+
export interface InstallCrashHandlerOptions {
|
|
72
|
+
/** Terminator (default {@link process.exit}). Injectable for tests. */
|
|
73
|
+
exit?: (code: number) => void;
|
|
74
|
+
/** Snapshot-context source (default the module crash context). */
|
|
75
|
+
getContext?: () => CrashContext;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Install the process-level crash handler (idempotent). Registers `uncaughtException` and
|
|
79
|
+
* `unhandledRejection` listeners that write a redacted snapshot and exit. Inert on a normal exit —
|
|
80
|
+
* no `exit`/`beforeExit` hook is registered, so a clean run behaves exactly as before.
|
|
81
|
+
*/
|
|
82
|
+
export declare function installCrashHandler(options?: InstallCrashHandlerOptions): void;
|
|
83
|
+
/**
|
|
84
|
+
* Remove the crash-handler listeners and reset internal state. Primarily for tests (so the module
|
|
85
|
+
* singleton's `handling`/`installed` flags don't leak between cases); harmless in production.
|
|
86
|
+
*/
|
|
87
|
+
export declare function uninstallCrashHandler(): void;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { writeSync } from 'node:fs';
|
|
2
|
+
import { writeCrashSnapshot } from '#src/utils/debugDump.js';
|
|
3
|
+
/** The live context read at crash time. Updated in place by the running session (see below). */
|
|
4
|
+
let crashContext = {};
|
|
5
|
+
/** Replace the crash context wholesale. */
|
|
6
|
+
export function setCrashContext(ctx) {
|
|
7
|
+
crashContext = ctx ?? {};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Merge a partial update into the crash context. The running agent calls this as it learns things
|
|
11
|
+
* (config at init, transcript tail before each turn) so a crash mid-run captures the latest state.
|
|
12
|
+
*/
|
|
13
|
+
export function updateCrashContext(patch) {
|
|
14
|
+
crashContext = { ...crashContext, ...patch };
|
|
15
|
+
}
|
|
16
|
+
/** Clear the crash context (e.g. when a session ends). */
|
|
17
|
+
export function clearCrashContext() {
|
|
18
|
+
crashContext = {};
|
|
19
|
+
}
|
|
20
|
+
/** Read the current crash context (used as the default context source by the installed handler). */
|
|
21
|
+
export function getCrashContext() {
|
|
22
|
+
return crashContext;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Re-entry guard. Module-level so it survives across the two listeners and any nested failure: once
|
|
26
|
+
* we are handling a crash, a second crash (including one thrown by the handler itself) must NOT
|
|
27
|
+
* re-run the snapshot logic — it goes straight to exit.
|
|
28
|
+
*/
|
|
29
|
+
let handling = false;
|
|
30
|
+
/** Whether {@link installCrashHandler} has already registered listeners (idempotent install). */
|
|
31
|
+
let installed = false;
|
|
32
|
+
let onUncaughtException;
|
|
33
|
+
let onUnhandledRejection;
|
|
34
|
+
/** A short, never-throwing, single-block rendering of the original error for stderr. */
|
|
35
|
+
function describeError(error) {
|
|
36
|
+
try {
|
|
37
|
+
if (error instanceof Error) {
|
|
38
|
+
return error.stack ?? `${error.name}: ${error.message}`;
|
|
39
|
+
}
|
|
40
|
+
return String(error);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return '<unprintable error>';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Write a line to fd 2 (stderr) synchronously, swallowing any failure — last-resort output. */
|
|
47
|
+
function writeStderr(line) {
|
|
48
|
+
try {
|
|
49
|
+
writeSync(2, line);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Nothing more we can safely do if even fd 2 is gone.
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The crash-handling body. Exported (rather than only closed over by the listeners) so it can be
|
|
57
|
+
* unit-tested directly with an injected `exit` and `getContext`, without registering real process
|
|
58
|
+
* listeners or killing the test runner.
|
|
59
|
+
*
|
|
60
|
+
* @param error the thrown value / rejection reason
|
|
61
|
+
* @param origin `'uncaughtException'` | `'unhandledRejection'`
|
|
62
|
+
* @param exit terminator (default {@link process.exit}); injectable so tests capture the code
|
|
63
|
+
* @param getContext source of the snapshot context (default the module context)
|
|
64
|
+
*/
|
|
65
|
+
export function handleCrash(error, origin, exit = (code) => process.exit(code), getContext = getCrashContext) {
|
|
66
|
+
// GUARD FIRST — before touching anything that could throw — so a failure below (or a crash raised
|
|
67
|
+
// WHILE handling) can never re-enter and loop.
|
|
68
|
+
if (handling) {
|
|
69
|
+
writeStderr(`\n[gaunt-sloth] crash handler re-entered while handling ${origin}; exiting.\n`);
|
|
70
|
+
exit(1);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
handling = true;
|
|
74
|
+
const original = describeError(error);
|
|
75
|
+
try {
|
|
76
|
+
const ctx = getContext();
|
|
77
|
+
const { crashDir } = writeCrashSnapshot({
|
|
78
|
+
error,
|
|
79
|
+
origin,
|
|
80
|
+
config: ctx.config,
|
|
81
|
+
modelDisplayName: ctx.modelDisplayName,
|
|
82
|
+
transcriptTail: ctx.transcriptTail,
|
|
83
|
+
});
|
|
84
|
+
// Surface the ORIGINAL error first (Node's own auto-print is suppressed by our listener), then
|
|
85
|
+
// the snapshot path. writeSync so the path is not truncated by the imminent process.exit.
|
|
86
|
+
writeStderr(`\n[gaunt-sloth] fatal ${origin}:\n${original}\n`);
|
|
87
|
+
writeStderr(`[gaunt-sloth] crash snapshot written to: ${crashDir}\n`);
|
|
88
|
+
}
|
|
89
|
+
catch (snapErr) {
|
|
90
|
+
// Snapshotting itself failed — DEGRADE: still surface the original error + a short reason, never
|
|
91
|
+
// mask it, never re-enter.
|
|
92
|
+
const reason = snapErr instanceof Error ? snapErr.message : String(snapErr);
|
|
93
|
+
writeStderr(`\n[gaunt-sloth] fatal ${origin}:\n${original}\n`);
|
|
94
|
+
writeStderr(`[gaunt-sloth] failed to write crash snapshot: ${reason}\n`);
|
|
95
|
+
}
|
|
96
|
+
exit(1);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Install the process-level crash handler (idempotent). Registers `uncaughtException` and
|
|
100
|
+
* `unhandledRejection` listeners that write a redacted snapshot and exit. Inert on a normal exit —
|
|
101
|
+
* no `exit`/`beforeExit` hook is registered, so a clean run behaves exactly as before.
|
|
102
|
+
*/
|
|
103
|
+
export function installCrashHandler(options = {}) {
|
|
104
|
+
if (installed)
|
|
105
|
+
return;
|
|
106
|
+
installed = true;
|
|
107
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
108
|
+
const getContext = options.getContext ?? getCrashContext;
|
|
109
|
+
onUncaughtException = (error) => handleCrash(error, 'uncaughtException', exit, getContext);
|
|
110
|
+
onUnhandledRejection = (reason) => handleCrash(reason, 'unhandledRejection', exit, getContext);
|
|
111
|
+
process.on('uncaughtException', onUncaughtException);
|
|
112
|
+
process.on('unhandledRejection', onUnhandledRejection);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Remove the crash-handler listeners and reset internal state. Primarily for tests (so the module
|
|
116
|
+
* singleton's `handling`/`installed` flags don't leak between cases); harmless in production.
|
|
117
|
+
*/
|
|
118
|
+
export function uninstallCrashHandler() {
|
|
119
|
+
if (onUncaughtException)
|
|
120
|
+
process.removeListener('uncaughtException', onUncaughtException);
|
|
121
|
+
if (onUnhandledRejection)
|
|
122
|
+
process.removeListener('unhandledRejection', onUnhandledRejection);
|
|
123
|
+
onUncaughtException = undefined;
|
|
124
|
+
onUnhandledRejection = undefined;
|
|
125
|
+
installed = false;
|
|
126
|
+
handling = false;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=crashHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crashHandler.js","sourceRoot":"","sources":["../../src/utils/crashHandler.ts"],"names":[],"mappings":"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"}
|