@vacbo/opencode-anthropic-fix 0.1.7 → 0.1.9
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 +88 -88
- package/dist/opencode-anthropic-auth-cli.mjs +804 -507
- package/dist/opencode-anthropic-auth-plugin.js +4751 -4109
- package/package.json +67 -59
- package/src/__tests__/billing-edge-cases.test.ts +59 -59
- package/src/__tests__/bun-proxy.parallel.test.ts +388 -382
- package/src/__tests__/cc-comparison.test.ts +87 -87
- package/src/__tests__/cc-credentials.test.ts +254 -250
- package/src/__tests__/cch-drift-checker.test.ts +51 -51
- package/src/__tests__/cch-native-style.test.ts +56 -56
- package/src/__tests__/debug-gating.test.ts +42 -42
- package/src/__tests__/decomposition-smoke.test.ts +68 -68
- package/src/__tests__/fingerprint-regression.test.ts +575 -566
- package/src/__tests__/helpers/conversation-history.smoke.test.ts +271 -271
- package/src/__tests__/helpers/conversation-history.ts +119 -119
- package/src/__tests__/helpers/deferred.smoke.test.ts +103 -103
- package/src/__tests__/helpers/deferred.ts +69 -69
- package/src/__tests__/helpers/in-memory-storage.smoke.test.ts +155 -155
- package/src/__tests__/helpers/in-memory-storage.ts +88 -88
- package/src/__tests__/helpers/mock-bun-proxy.smoke.test.ts +68 -68
- package/src/__tests__/helpers/mock-bun-proxy.ts +189 -189
- package/src/__tests__/helpers/plugin-fetch-harness.smoke.test.ts +273 -273
- package/src/__tests__/helpers/plugin-fetch-harness.ts +288 -288
- package/src/__tests__/helpers/sse.smoke.test.ts +236 -236
- package/src/__tests__/helpers/sse.ts +209 -209
- package/src/__tests__/index.parallel.test.ts +605 -595
- package/src/__tests__/sanitization-regex.test.ts +112 -112
- package/src/__tests__/state-bounds.test.ts +90 -90
- package/src/account-identity.test.ts +197 -192
- package/src/account-identity.ts +69 -67
- package/src/account-state.test.ts +86 -86
- package/src/account-state.ts +25 -25
- package/src/accounts/matching.test.ts +335 -0
- package/src/accounts/matching.ts +167 -0
- package/src/accounts/persistence.test.ts +345 -0
- package/src/accounts/persistence.ts +432 -0
- package/src/accounts/repair.test.ts +276 -0
- package/src/accounts/repair.ts +407 -0
- package/src/accounts.dedup.test.ts +621 -621
- package/src/accounts.test.ts +933 -929
- package/src/accounts.ts +633 -989
- package/src/backoff.test.ts +345 -345
- package/src/backoff.ts +219 -219
- package/src/betas.ts +124 -124
- package/src/bun-fetch.test.ts +345 -342
- package/src/bun-fetch.ts +424 -424
- package/src/bun-proxy.test.ts +25 -25
- package/src/bun-proxy.ts +209 -209
- package/src/cc-credentials.ts +111 -111
- package/src/circuit-breaker.test.ts +184 -184
- package/src/circuit-breaker.ts +169 -169
- package/src/cli/commands/auth.ts +963 -0
- package/src/cli/commands/config.ts +547 -0
- package/src/cli/formatting.test.ts +406 -0
- package/src/cli/formatting.ts +219 -0
- package/src/cli.ts +255 -2022
- package/src/commands/handlers/betas.ts +100 -0
- package/src/commands/handlers/config.ts +99 -0
- package/src/commands/handlers/files.ts +375 -0
- package/src/commands/oauth-flow.ts +181 -166
- package/src/commands/prompts.ts +61 -61
- package/src/commands/router.test.ts +421 -0
- package/src/commands/router.ts +143 -635
- package/src/config.test.ts +482 -482
- package/src/config.ts +412 -404
- package/src/constants.ts +48 -48
- package/src/drift/cch-constants.ts +95 -95
- package/src/env.ts +111 -105
- package/src/headers/billing.ts +33 -33
- package/src/headers/builder.ts +130 -130
- package/src/headers/cch.ts +75 -75
- package/src/headers/stainless.ts +25 -25
- package/src/headers/user-agent.ts +23 -23
- package/src/index.ts +436 -828
- package/src/models.ts +27 -27
- package/src/oauth.test.ts +102 -102
- package/src/oauth.ts +178 -178
- package/src/parent-pid-watcher.test.ts +148 -148
- package/src/parent-pid-watcher.ts +69 -69
- package/src/plugin-helpers.ts +82 -82
- package/src/refresh-helpers.ts +145 -139
- package/src/refresh-lock.test.ts +94 -94
- package/src/refresh-lock.ts +93 -93
- package/src/request/body.history.test.ts +579 -571
- package/src/request/body.ts +255 -255
- package/src/request/metadata.ts +65 -65
- package/src/request/retry.test.ts +156 -156
- package/src/request/retry.ts +67 -67
- package/src/request/url.ts +21 -21
- package/src/request-orchestration-helpers.ts +648 -0
- package/src/response/index.ts +5 -5
- package/src/response/mcp.ts +58 -58
- package/src/response/streaming.test.ts +313 -311
- package/src/response/streaming.ts +412 -410
- package/src/rotation.test.ts +304 -301
- package/src/rotation.ts +205 -205
- package/src/storage.test.ts +547 -547
- package/src/storage.ts +315 -291
- package/src/system-prompt/builder.ts +38 -38
- package/src/system-prompt/index.ts +5 -5
- package/src/system-prompt/normalize.ts +60 -60
- package/src/system-prompt/sanitize.ts +30 -30
- package/src/thinking.ts +21 -20
- package/src/token-refresh.test.ts +265 -265
- package/src/token-refresh.ts +219 -214
- package/src/types.ts +30 -30
- package/dist/bun-proxy.mjs +0 -291
|
@@ -8,212 +8,212 @@ const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "pla
|
|
|
8
8
|
const originalPpidDescriptor = Object.getOwnPropertyDescriptor(process, "ppid");
|
|
9
9
|
|
|
10
10
|
function restorePlatform(): void {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (originalPlatformDescriptor) {
|
|
12
|
+
Object.defineProperty(process, "platform", originalPlatformDescriptor);
|
|
13
|
+
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function setPlatform(platform: NodeJS.Platform): void {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
Object.defineProperty(process, "platform", {
|
|
18
|
+
value: platform,
|
|
19
|
+
configurable: true,
|
|
20
|
+
});
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function restoreParentPid(): void {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
if (originalPpidDescriptor) {
|
|
25
|
+
Object.defineProperty(process, "ppid", originalPpidDescriptor);
|
|
26
|
+
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function setCurrentParentPid(ppid: number): void {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
Object.defineProperty(process, "ppid", {
|
|
31
|
+
value: ppid,
|
|
32
|
+
configurable: true,
|
|
33
|
+
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function makeProcessError(code: "EPERM" | "ESRCH"): NodeJS.ErrnoException {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const error = new Error(`process.kill failed with ${code}`) as NodeJS.ErrnoException;
|
|
38
|
+
error.code = code;
|
|
39
|
+
return error;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
describe("ParentPidWatcher", () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
afterEach(() => {
|
|
50
|
-
vi.useRealTimers();
|
|
51
|
-
vi.restoreAllMocks();
|
|
52
|
-
restorePlatform();
|
|
53
|
-
restoreParentPid();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("starts polling parent PID every 5 seconds by default", () => {
|
|
57
|
-
const onParentGone = vi.fn();
|
|
58
|
-
const intervalSpy = vi.spyOn(globalThis, "setInterval");
|
|
59
|
-
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
60
|
-
|
|
61
|
-
const watcher = new ParentPidWatcher({
|
|
62
|
-
parentPid: 4242,
|
|
63
|
-
onParentGone,
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
vi.useFakeTimers();
|
|
45
|
+
restorePlatform();
|
|
46
|
+
restoreParentPid();
|
|
64
47
|
});
|
|
65
48
|
|
|
66
|
-
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
vi.useRealTimers();
|
|
51
|
+
vi.restoreAllMocks();
|
|
52
|
+
restorePlatform();
|
|
53
|
+
restoreParentPid();
|
|
54
|
+
});
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
it("starts polling parent PID every 5 seconds by default", () => {
|
|
57
|
+
const onParentGone = vi.fn();
|
|
58
|
+
const intervalSpy = vi.spyOn(globalThis, "setInterval");
|
|
59
|
+
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
70
60
|
|
|
71
|
-
|
|
61
|
+
const watcher = new ParentPidWatcher({
|
|
62
|
+
parentPid: 4242,
|
|
63
|
+
onParentGone,
|
|
64
|
+
});
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
expect(onParentGone).not.toHaveBeenCalled();
|
|
75
|
-
});
|
|
66
|
+
watcher.start();
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
expect(intervalSpy).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(intervalSpy).toHaveBeenLastCalledWith(expect.any(Function), 5000);
|
|
79
70
|
|
|
80
|
-
|
|
81
|
-
throw makeProcessError("ESRCH");
|
|
82
|
-
});
|
|
71
|
+
vi.advanceTimersByTime(5000);
|
|
83
72
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
onParentGone,
|
|
73
|
+
expect(killSpy).toHaveBeenCalledWith(4242, 0);
|
|
74
|
+
expect(onParentGone).not.toHaveBeenCalled();
|
|
87
75
|
});
|
|
88
76
|
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
it("fires the callback when process.kill(parentPid, 0) reports ESRCH", () => {
|
|
78
|
+
const onParentGone = vi.fn();
|
|
91
79
|
|
|
92
|
-
|
|
93
|
-
|
|
80
|
+
vi.spyOn(process, "kill").mockImplementation(() => {
|
|
81
|
+
throw makeProcessError("ESRCH");
|
|
82
|
+
});
|
|
94
83
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
84
|
+
const watcher = new ParentPidWatcher({
|
|
85
|
+
parentPid: 4242,
|
|
86
|
+
onParentGone,
|
|
87
|
+
});
|
|
98
88
|
|
|
99
|
-
|
|
89
|
+
watcher.start();
|
|
90
|
+
vi.advanceTimersByTime(5000);
|
|
100
91
|
|
|
101
|
-
|
|
102
|
-
parentPid: 4242,
|
|
103
|
-
onParentGone,
|
|
92
|
+
expect(onParentGone).toHaveBeenCalledTimes(1);
|
|
104
93
|
});
|
|
105
94
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
it("fires the callback when process.ppid changes away from the configured parent PID", () => {
|
|
96
|
+
const onParentGone = vi.fn();
|
|
97
|
+
setCurrentParentPid(4242);
|
|
109
98
|
|
|
110
|
-
|
|
111
|
-
});
|
|
99
|
+
vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
112
100
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
101
|
+
const watcher = new ParentPidWatcher({
|
|
102
|
+
parentPid: 4242,
|
|
103
|
+
onParentGone,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
watcher.start();
|
|
107
|
+
setCurrentParentPid(9001);
|
|
108
|
+
vi.advanceTimersByTime(5000);
|
|
109
|
+
|
|
110
|
+
expect(onParentGone).toHaveBeenCalledTimes(1);
|
|
118
111
|
});
|
|
119
112
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
it("stops polling after the callback fires", () => {
|
|
114
|
+
const onParentGone = vi.fn();
|
|
115
|
+
const clearIntervalSpy = vi.spyOn(globalThis, "clearInterval");
|
|
116
|
+
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => {
|
|
117
|
+
throw makeProcessError("ESRCH");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const watcher = new ParentPidWatcher({
|
|
121
|
+
parentPid: 4242,
|
|
122
|
+
onParentGone,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
watcher.start();
|
|
126
|
+
vi.advanceTimersByTime(5000);
|
|
127
|
+
vi.advanceTimersByTime(20_000);
|
|
128
|
+
|
|
129
|
+
expect(onParentGone).toHaveBeenCalledTimes(1);
|
|
130
|
+
expect(killSpy).toHaveBeenCalledTimes(1);
|
|
131
|
+
expect(clearIntervalSpy).toHaveBeenCalledTimes(1);
|
|
123
132
|
});
|
|
124
133
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
it("manual stop() halts polling", () => {
|
|
135
|
+
const onParentGone = vi.fn();
|
|
136
|
+
const clearIntervalSpy = vi.spyOn(globalThis, "clearInterval");
|
|
137
|
+
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
128
138
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
const watcher = new ParentPidWatcher({
|
|
140
|
+
parentPid: 4242,
|
|
141
|
+
pollIntervalMs: 1000,
|
|
142
|
+
onParentGone,
|
|
143
|
+
});
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
145
|
+
watcher.start();
|
|
146
|
+
watcher.stop();
|
|
147
|
+
vi.advanceTimersByTime(10_000);
|
|
138
148
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
onParentGone,
|
|
149
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
150
|
+
expect(onParentGone).not.toHaveBeenCalled();
|
|
151
|
+
expect(clearIntervalSpy).toHaveBeenCalledTimes(1);
|
|
143
152
|
});
|
|
144
153
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
it("does not start polling for invalid parent PIDs", () => {
|
|
155
|
+
const intervalSpy = vi.spyOn(globalThis, "setInterval");
|
|
156
|
+
const onParentGone = vi.fn();
|
|
148
157
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
expect(() => new ParentPidWatcher({ parentPid: 0, onParentGone }).start()).toThrow(/parent pid/i);
|
|
159
|
+
expect(() => new ParentPidWatcher({ parentPid: -1, onParentGone }).start()).toThrow(/parent pid/i);
|
|
160
|
+
expect(() => new ParentPidWatcher({ parentPid: Number.NaN, onParentGone }).start()).toThrow(/parent pid/i);
|
|
161
|
+
expect(intervalSpy).not.toHaveBeenCalled();
|
|
162
|
+
});
|
|
153
163
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
it("treats EPERM as parent-still-alive on macOS", () => {
|
|
165
|
+
const onParentGone = vi.fn();
|
|
166
|
+
setPlatform("darwin");
|
|
157
167
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
expect(intervalSpy).not.toHaveBeenCalled();
|
|
162
|
-
});
|
|
168
|
+
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => {
|
|
169
|
+
throw makeProcessError("EPERM");
|
|
170
|
+
});
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
172
|
+
const watcher = new ParentPidWatcher({
|
|
173
|
+
parentPid: 4242,
|
|
174
|
+
onParentGone,
|
|
175
|
+
});
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
});
|
|
177
|
+
watcher.start();
|
|
178
|
+
vi.advanceTimersByTime(5000);
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
onParentGone,
|
|
180
|
+
expect(killSpy).toHaveBeenCalledWith(4242, 0);
|
|
181
|
+
expect(onParentGone).not.toHaveBeenCalled();
|
|
175
182
|
});
|
|
176
183
|
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
it("treats EPERM as parent-still-alive on Linux", () => {
|
|
185
|
+
const onParentGone = vi.fn();
|
|
186
|
+
setPlatform("linux");
|
|
179
187
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
188
|
+
const killSpy = vi.spyOn(process, "kill").mockImplementation(() => {
|
|
189
|
+
throw makeProcessError("EPERM");
|
|
190
|
+
});
|
|
183
191
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
const watcher = new ParentPidWatcher({
|
|
193
|
+
parentPid: 4242,
|
|
194
|
+
onParentGone,
|
|
195
|
+
});
|
|
187
196
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
197
|
+
watcher.start();
|
|
198
|
+
vi.advanceTimersByTime(5000);
|
|
191
199
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
onParentGone,
|
|
200
|
+
expect(killSpy).toHaveBeenCalledWith(4242, 0);
|
|
201
|
+
expect(onParentGone).not.toHaveBeenCalled();
|
|
195
202
|
});
|
|
196
203
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
expect(killSpy).toHaveBeenCalledWith(4242, 0);
|
|
201
|
-
expect(onParentGone).not.toHaveBeenCalled();
|
|
202
|
-
});
|
|
204
|
+
it("uses the same parent-death contract on Windows via watchParentAndExit", () => {
|
|
205
|
+
setPlatform("win32");
|
|
203
206
|
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation((() => undefined) as never);
|
|
208
|
+
vi.spyOn(process, "kill").mockImplementation(() => {
|
|
209
|
+
throw makeProcessError("ESRCH");
|
|
210
|
+
});
|
|
206
211
|
|
|
207
|
-
|
|
208
|
-
vi.spyOn(process, "kill").mockImplementation(() => {
|
|
209
|
-
throw makeProcessError("ESRCH");
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
const watcher = watchParentAndExit(4242, 7);
|
|
212
|
+
const watcher = watchParentAndExit(4242, 7);
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
watcher.start();
|
|
215
|
+
vi.advanceTimersByTime(5000);
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
expect(exitSpy).toHaveBeenCalledWith(7);
|
|
218
|
+
});
|
|
219
219
|
});
|
|
@@ -2,98 +2,98 @@ const DEFAULT_POLL_INTERVAL_MS = 5_000;
|
|
|
2
2
|
const DEFAULT_PARENT_EXIT_CODE = 1;
|
|
3
3
|
|
|
4
4
|
export interface ParentPidWatcherOptions {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
parentPid: number;
|
|
6
|
+
pollIntervalMs?: number;
|
|
7
|
+
onParentGone: () => void;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
function assertValidParentPid(parentPid: number): void {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (!Number.isInteger(parentPid) || parentPid <= 0) {
|
|
12
|
+
throw new Error("Parent PID must be a positive integer.");
|
|
13
|
+
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function assertValidPollInterval(pollIntervalMs: number): void {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if (!Number.isFinite(pollIntervalMs) || pollIntervalMs <= 0) {
|
|
18
|
+
throw new Error("Poll interval must be a positive number.");
|
|
19
|
+
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function isParentAlive(parentPid: number): boolean {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
try {
|
|
24
|
+
process.kill(parentPid, 0);
|
|
25
|
+
return true;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
28
|
+
if (code === "ESRCH") {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (code === "EPERM") {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true;
|
|
30
37
|
}
|
|
31
|
-
|
|
32
|
-
if (code === "EPERM") {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export class ParentPidWatcher {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
start(): void {
|
|
55
|
-
if (this.interval) {
|
|
56
|
-
return;
|
|
41
|
+
private readonly parentPid: number;
|
|
42
|
+
private readonly pollIntervalMs: number;
|
|
43
|
+
private readonly onParentGone: () => void;
|
|
44
|
+
|
|
45
|
+
private interval: ReturnType<typeof setInterval> | null = null;
|
|
46
|
+
private shouldMonitorPpidDrift = false;
|
|
47
|
+
|
|
48
|
+
constructor(options: ParentPidWatcherOptions) {
|
|
49
|
+
this.parentPid = options.parentPid;
|
|
50
|
+
this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
51
|
+
this.onParentGone = options.onParentGone;
|
|
57
52
|
}
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
start(): void {
|
|
55
|
+
if (this.interval) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
assertValidParentPid(this.parentPid);
|
|
60
|
+
assertValidPollInterval(this.pollIntervalMs);
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
if (this.shouldMonitorPpidDrift && process.ppid !== this.parentPid) {
|
|
66
|
-
this.handleParentGone();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
62
|
+
this.shouldMonitorPpidDrift = process.ppid === this.parentPid;
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
this.interval = setInterval(() => {
|
|
65
|
+
if (this.shouldMonitorPpidDrift && process.ppid !== this.parentPid) {
|
|
66
|
+
this.handleParentGone();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
if (!isParentAlive(this.parentPid)) {
|
|
71
|
+
this.handleParentGone();
|
|
72
|
+
}
|
|
73
|
+
}, this.pollIntervalMs);
|
|
79
74
|
}
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
stop(): void {
|
|
77
|
+
if (!this.interval) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
85
80
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
clearInterval(this.interval);
|
|
82
|
+
this.interval = null;
|
|
83
|
+
this.shouldMonitorPpidDrift = false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private handleParentGone(): void {
|
|
87
|
+
this.stop();
|
|
88
|
+
this.onParentGone();
|
|
89
|
+
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export function watchParentAndExit(parentPid: number, exitCode = DEFAULT_PARENT_EXIT_CODE): ParentPidWatcher {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
return new ParentPidWatcher({
|
|
94
|
+
parentPid,
|
|
95
|
+
onParentGone: () => {
|
|
96
|
+
process.exit(exitCode);
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
99
|
}
|