@github/copilot-sdk 1.0.13-preview.6 → 1.0.14-preview.0
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 +42 -0
- package/dist/cjs/cliVersion.js +1 -1
- package/dist/cjs/client.js +44 -9
- package/dist/cjs/ffiRuntimeHost.js +140 -55
- package/dist/cjs/generated/rpc.js +104 -10
- package/dist/cjs/session.js +109 -10
- package/dist/cliVersion.d.ts +1 -1
- package/dist/cliVersion.js +1 -1
- package/dist/client.d.ts +4 -0
- package/dist/client.js +44 -9
- package/dist/ffiRuntimeHost.d.ts +8 -2
- package/dist/ffiRuntimeHost.js +140 -55
- package/dist/generated/rpc.d.ts +1399 -60
- package/dist/generated/rpc.js +104 -10
- package/dist/generated/session-events.d.ts +632 -25
- package/dist/index.d.ts +1 -1
- package/dist/session.d.ts +52 -1
- package/dist/session.js +109 -10
- package/dist/types.d.ts +28 -4
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -267,11 +267,26 @@ Send a message to the session. Returns immediately after the message is queued;
|
|
|
267
267
|
**Options:**
|
|
268
268
|
|
|
269
269
|
- `prompt: string` - The message/prompt to send
|
|
270
|
+
- `source?: MessageSource` - `"user"`, `"system"`, or `` `agent-${string}` `` provenance; omitted by default
|
|
270
271
|
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
271
272
|
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
272
273
|
|
|
273
274
|
Returns the message ID.
|
|
274
275
|
|
|
276
|
+
Use `source: "system"` for automated messages from your application:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
await session.send({ prompt: "Context updated", source: "system" });
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
For a message from another agent, use its trusted sender ID:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Source is independent of delivery mode. Leaving it unset preserves the existing human-message payload; it does not set billing flags or use the notification API.
|
|
289
|
+
|
|
275
290
|
##### `sendAndWait(options: MessageOptions, timeout?: number): Promise<AssistantMessageEvent | undefined>`
|
|
276
291
|
|
|
277
292
|
Send a message and wait until the session becomes idle.
|
|
@@ -279,6 +294,7 @@ Send a message and wait until the session becomes idle.
|
|
|
279
294
|
**Options:**
|
|
280
295
|
|
|
281
296
|
- `prompt: string` - The message/prompt to send
|
|
297
|
+
- `source?: MessageSource` - Same optional provenance as `send`
|
|
282
298
|
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
283
299
|
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
284
300
|
- `timeout?: number` - Optional timeout in milliseconds
|
|
@@ -319,6 +335,32 @@ const unsubscribe = session.on((event) => {
|
|
|
319
335
|
unsubscribe();
|
|
320
336
|
```
|
|
321
337
|
|
|
338
|
+
##### `setModel(model: string, options?): Promise<void>`
|
|
339
|
+
|
|
340
|
+
Change the model for this session. The new model takes effect for the next message; conversation history is preserved.
|
|
341
|
+
|
|
342
|
+
**Options:**
|
|
343
|
+
|
|
344
|
+
- `reasoningEffort?: string` - Reasoning effort level
|
|
345
|
+
- `autoTier?: AutoTier | null` - Auto routing preference to stage together with selecting `auto`. Pass `null` to return to the provider's default Auto routing; omit it to leave the current preference unchanged.
|
|
346
|
+
|
|
347
|
+
##### `setAutoTier(autoTier: AutoTier | null): Promise<ModelSwitchAutoTierResult>`
|
|
348
|
+
|
|
349
|
+
Change the Auto routing preference without changing the selected model. Pass `null` to return to the provider's default Auto routing.
|
|
350
|
+
|
|
351
|
+
The runtime does not apply the preference immediately. It records the request and commits it only when a later user turn using the `auto` model successfully obtains a usable model from the provider, so a `pending` status confirms acceptance rather than effect. Only the most recent request survives.
|
|
352
|
+
|
|
353
|
+
Watch for the outcome through the `session.model_change` event on success or the ephemeral `session.auto_tier_switch_failed` event on failure, and read the authoritative state at any time with `session.rpc.model.getCurrent()`.
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
const result = await session.setAutoTier("intelligence");
|
|
357
|
+
if (result.status === "pending") {
|
|
358
|
+
// Accepted, but not yet in effect.
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
See [Auto tier persistence](../docs/features/session-persistence.md#auto-tier-persistence) for the full lifecycle rules.
|
|
363
|
+
|
|
322
364
|
##### `abort(): Promise<void>`
|
|
323
365
|
|
|
324
366
|
Abort the currently processing message in this session.
|
package/dist/cjs/cliVersion.js
CHANGED
|
@@ -22,7 +22,7 @@ __export(cliVersion_exports, {
|
|
|
22
22
|
COPILOT_CLI_VERSION: () => COPILOT_CLI_VERSION
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(cliVersion_exports);
|
|
25
|
-
const COPILOT_CLI_VERSION = "1.0.
|
|
25
|
+
const COPILOT_CLI_VERSION = "1.0.84-5";
|
|
26
26
|
const COPILOT_CLI_USE_NPM_PACKAGE = false;
|
|
27
27
|
// Annotate the CommonJS export names for ESM import in node:
|
|
28
28
|
0 && (module.exports = {
|
package/dist/cjs/client.js
CHANGED
|
@@ -236,10 +236,13 @@ class CopilotClient {
|
|
|
236
236
|
ffiHost = null;
|
|
237
237
|
connection = null;
|
|
238
238
|
messageWriter = null;
|
|
239
|
+
connectionClosed = false;
|
|
239
240
|
socket = null;
|
|
240
241
|
runtimePort = null;
|
|
241
242
|
actualHost = "localhost";
|
|
242
243
|
state = "disconnected";
|
|
244
|
+
/** Shared in-flight start; concurrent callers await it instead of spawning another CLI. */
|
|
245
|
+
startPromise = null;
|
|
243
246
|
sessions = /* @__PURE__ */ new Map();
|
|
244
247
|
stderrBuffer = "";
|
|
245
248
|
// Captures CLI stderr for error messages
|
|
@@ -617,7 +620,19 @@ class CopilotClient {
|
|
|
617
620
|
if (this.state === "connected") {
|
|
618
621
|
return;
|
|
619
622
|
}
|
|
623
|
+
if (this.startPromise) {
|
|
624
|
+
return this.startPromise;
|
|
625
|
+
}
|
|
626
|
+
this.startPromise = this.doStart();
|
|
627
|
+
try {
|
|
628
|
+
await this.startPromise;
|
|
629
|
+
} finally {
|
|
630
|
+
this.startPromise = null;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
async doStart() {
|
|
620
634
|
this.forceStopping = false;
|
|
635
|
+
this.connectionClosed = false;
|
|
621
636
|
this.processTransportError = null;
|
|
622
637
|
this.state = "connecting";
|
|
623
638
|
try {
|
|
@@ -716,7 +731,7 @@ class CopilotClient {
|
|
|
716
731
|
}
|
|
717
732
|
this.sessions.clear();
|
|
718
733
|
this.githubTokenProviders.clear();
|
|
719
|
-
if (this.connection && (this.cliProcess || this.ffiHost) && !this.isExternalServer) {
|
|
734
|
+
if (this.connection && !this.connectionClosed && (this.cliProcess || this.ffiHost) && !this.isExternalServer) {
|
|
720
735
|
const runtimeShutdownStart = Date.now();
|
|
721
736
|
const shutdownPromise = this.rpc.runtime.shutdown();
|
|
722
737
|
void shutdownPromise.catch(() => void 0);
|
|
@@ -805,7 +820,7 @@ class CopilotClient {
|
|
|
805
820
|
const host = this.ffiHost;
|
|
806
821
|
this.ffiHost = null;
|
|
807
822
|
try {
|
|
808
|
-
host.dispose();
|
|
823
|
+
await host.dispose();
|
|
809
824
|
} catch (error) {
|
|
810
825
|
errors.push(
|
|
811
826
|
new Error(
|
|
@@ -900,11 +915,12 @@ class CopilotClient {
|
|
|
900
915
|
this.cliProcess = null;
|
|
901
916
|
}
|
|
902
917
|
if (this.ffiHost) {
|
|
918
|
+
const host = this.ffiHost;
|
|
919
|
+
this.ffiHost = null;
|
|
903
920
|
try {
|
|
904
|
-
|
|
921
|
+
await host.dispose();
|
|
905
922
|
} catch {
|
|
906
923
|
}
|
|
907
|
-
this.ffiHost = null;
|
|
908
924
|
}
|
|
909
925
|
if (this.cliStartTimeout) {
|
|
910
926
|
clearTimeout(this.cliStartTimeout);
|
|
@@ -1221,6 +1237,7 @@ class CopilotClient {
|
|
|
1221
1237
|
...this.onGitHubTelemetry != null ? { enableGitHubTelemetryForwarding: true } : {},
|
|
1222
1238
|
mcpServers: toWireMcpServers(config.mcpServers),
|
|
1223
1239
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1240
|
+
authClientIdMetadataUrl: config.authClientIdMetadataUrl,
|
|
1224
1241
|
envValueMode: "direct",
|
|
1225
1242
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1226
1243
|
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
|
@@ -1281,6 +1298,7 @@ class CopilotClient {
|
|
|
1281
1298
|
await this.updateSessionOptionsForMode(session, config);
|
|
1282
1299
|
this.commitGitHubTokenProvider(returnedSessionId, gitHubTokenProviderRegistrationId);
|
|
1283
1300
|
} catch (e) {
|
|
1301
|
+
session?._markDisconnected();
|
|
1284
1302
|
if (registeredId !== void 0) {
|
|
1285
1303
|
this.sessions.delete(registeredId);
|
|
1286
1304
|
}
|
|
@@ -1465,6 +1483,7 @@ class CopilotClient {
|
|
|
1465
1483
|
...this.onGitHubTelemetry != null ? { enableGitHubTelemetryForwarding: true } : {},
|
|
1466
1484
|
mcpServers: toWireMcpServers(config.mcpServers),
|
|
1467
1485
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1486
|
+
authClientIdMetadataUrl: config.authClientIdMetadataUrl,
|
|
1468
1487
|
envValueMode: "direct",
|
|
1469
1488
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1470
1489
|
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
|
@@ -1513,6 +1532,7 @@ class CopilotClient {
|
|
|
1513
1532
|
await this.updateSessionOptionsForMode(session, config);
|
|
1514
1533
|
this.commitGitHubTokenProvider(sessionId, gitHubTokenProviderRegistrationId);
|
|
1515
1534
|
} catch (e) {
|
|
1535
|
+
session._markDisconnected();
|
|
1516
1536
|
this.sessions.delete(sessionId);
|
|
1517
1537
|
if (gitHubTokenProviderRegistrationId !== void 0) {
|
|
1518
1538
|
this.githubTokenProviders.delete(gitHubTokenProviderRegistrationId);
|
|
@@ -1628,7 +1648,10 @@ class CopilotClient {
|
|
|
1628
1648
|
const raceAgainstExit = (p) => this.processExitPromise ? Promise.race([p, this.processExitPromise]) : p;
|
|
1629
1649
|
let serverVersion;
|
|
1630
1650
|
try {
|
|
1631
|
-
const connectParams = {
|
|
1651
|
+
const connectParams = {
|
|
1652
|
+
token: this.effectiveConnectionToken,
|
|
1653
|
+
supportedTaskKinds: ["agent", "client", "shell"]
|
|
1654
|
+
};
|
|
1632
1655
|
if (this.onGitHubTelemetry != null) {
|
|
1633
1656
|
connectParams.enableGitHubTelemetryForwarding = true;
|
|
1634
1657
|
}
|
|
@@ -2259,12 +2282,24 @@ stderr: ${stderrOutput}` : ""}`
|
|
|
2259
2282
|
return await this.handleHooksInvoke(params);
|
|
2260
2283
|
}
|
|
2261
2284
|
);
|
|
2262
|
-
this.connection
|
|
2285
|
+
const connection = this.connection;
|
|
2286
|
+
const markDisconnected = () => {
|
|
2287
|
+
if (this.connection !== connection) {
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
this.connectionClosed = true;
|
|
2263
2291
|
this.state = "disconnected";
|
|
2292
|
+
for (const session of this.sessions.values()) {
|
|
2293
|
+
session._markDisconnected();
|
|
2294
|
+
}
|
|
2295
|
+
this.sessions.clear();
|
|
2264
2296
|
this.githubTokenProviders.clear();
|
|
2265
|
-
}
|
|
2266
|
-
this.connection.
|
|
2267
|
-
|
|
2297
|
+
};
|
|
2298
|
+
this.connection.onClose(markDisconnected);
|
|
2299
|
+
this.connection.onError(() => {
|
|
2300
|
+
if (this.connection === connection) {
|
|
2301
|
+
this.state = "disconnected";
|
|
2302
|
+
}
|
|
2268
2303
|
});
|
|
2269
2304
|
}
|
|
2270
2305
|
handleSessionEventNotification(notification) {
|
|
@@ -37,6 +37,7 @@ var import_node_path = require("node:path");
|
|
|
37
37
|
var import_node_stream = require("node:stream");
|
|
38
38
|
const SYMBOL_PREFIX = "copilot_runtime_";
|
|
39
39
|
const KEEP_ALIVE_INTERVAL_MS = 1 << 30;
|
|
40
|
+
const CLEANUP_RETRY_INTERVAL_MS = 100;
|
|
40
41
|
let loadedLibraryPath;
|
|
41
42
|
let loadedLibrary;
|
|
42
43
|
function loadLibrary(libraryPath) {
|
|
@@ -129,12 +130,16 @@ class FfiRuntimeHost {
|
|
|
129
130
|
cliEntrypoint;
|
|
130
131
|
environment;
|
|
131
132
|
args;
|
|
133
|
+
static quarantinedHosts = /* @__PURE__ */ new Set();
|
|
132
134
|
lib;
|
|
133
135
|
serverId = 0;
|
|
134
136
|
connectionId = 0;
|
|
135
137
|
disposed = false;
|
|
138
|
+
starting = false;
|
|
136
139
|
outboundCallback;
|
|
137
140
|
keepAliveTimer;
|
|
141
|
+
cleanupRetryTimer;
|
|
142
|
+
cleanupInProgress = false;
|
|
138
143
|
/** The stream JSON-RPC reads server→client frames from. */
|
|
139
144
|
receiveStream;
|
|
140
145
|
/** The stream JSON-RPC writes client→server frames to. */
|
|
@@ -156,49 +161,65 @@ class FfiRuntimeHost {
|
|
|
156
161
|
}
|
|
157
162
|
/** Starts the in-process Rust runtime and opens the FFI JSON-RPC connection. */
|
|
158
163
|
async start() {
|
|
164
|
+
if (this.disposed) {
|
|
165
|
+
throw new Error("The in-process runtime host is disposed.");
|
|
166
|
+
}
|
|
167
|
+
this.starting = true;
|
|
159
168
|
const argvJson = buildArgvJson(this.cliEntrypoint, this.args);
|
|
160
169
|
const envJson = buildEnvJson(this.environment);
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
try {
|
|
171
|
+
this.serverId = await new Promise((resolvePromise, rejectPromise) => {
|
|
172
|
+
this.lib.hostStart.async(
|
|
173
|
+
argvJson,
|
|
174
|
+
argvJson.length,
|
|
175
|
+
envJson,
|
|
176
|
+
envJson ? envJson.length : 0,
|
|
177
|
+
(error, result) => {
|
|
178
|
+
if (error) {
|
|
179
|
+
rejectPromise(error);
|
|
180
|
+
} else {
|
|
181
|
+
resolvePromise(result);
|
|
182
|
+
}
|
|
172
183
|
}
|
|
173
|
-
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
if (!this.serverId) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`copilot_runtime_host_start failed (library '${this.libraryPath}').`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (this.disposed) {
|
|
192
|
+
throw new Error("The in-process runtime host was disposed during startup.");
|
|
193
|
+
}
|
|
194
|
+
this.outboundCallback = import_koffi.default.register(
|
|
195
|
+
(_userData, bytesPtr, bytesLen) => this.feedInbound(bytesPtr, bytesLen),
|
|
196
|
+
this.lib.outboundCallbackType
|
|
174
197
|
);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
this.connectionId = this.lib.connectionOpen(
|
|
199
|
+
this.serverId,
|
|
200
|
+
this.outboundCallback,
|
|
201
|
+
null,
|
|
202
|
+
null,
|
|
203
|
+
0,
|
|
204
|
+
null,
|
|
205
|
+
0,
|
|
206
|
+
null,
|
|
207
|
+
0
|
|
208
|
+
);
|
|
209
|
+
if (!this.connectionId) {
|
|
210
|
+
this.unregisterCallback();
|
|
211
|
+
this.lib.hostShutdown(this.serverId);
|
|
212
|
+
this.serverId = 0;
|
|
213
|
+
throw new Error("copilot_runtime_connection_open failed.");
|
|
214
|
+
}
|
|
215
|
+
this.keepAliveTimer = setInterval(() => {
|
|
216
|
+
}, KEEP_ALIVE_INTERVAL_MS);
|
|
217
|
+
} finally {
|
|
218
|
+
this.starting = false;
|
|
219
|
+
if (this.disposed) {
|
|
220
|
+
void this.tryFinalizeCleanup();
|
|
221
|
+
}
|
|
199
222
|
}
|
|
200
|
-
this.keepAliveTimer = setInterval(() => {
|
|
201
|
-
}, KEEP_ALIVE_INTERVAL_MS);
|
|
202
223
|
}
|
|
203
224
|
writeFrame(frame) {
|
|
204
225
|
if (this.disposed || !this.connectionId) {
|
|
@@ -237,41 +258,105 @@ class FfiRuntimeHost {
|
|
|
237
258
|
}
|
|
238
259
|
unregisterCallback() {
|
|
239
260
|
if (this.outboundCallback === void 0) {
|
|
240
|
-
return;
|
|
261
|
+
return true;
|
|
241
262
|
}
|
|
242
263
|
const callback = this.outboundCallback;
|
|
243
|
-
this.outboundCallback = void 0;
|
|
244
264
|
try {
|
|
245
265
|
import_koffi.default.unregister(callback);
|
|
246
|
-
|
|
266
|
+
this.outboundCallback = void 0;
|
|
267
|
+
return true;
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(
|
|
270
|
+
`Failed to unregister in-process FFI callback: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
271
|
+
);
|
|
272
|
+
FfiRuntimeHost.quarantinedHosts.add(this);
|
|
273
|
+
return false;
|
|
247
274
|
}
|
|
248
275
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (this.disposed) {
|
|
276
|
+
scheduleCleanupRetry() {
|
|
277
|
+
if (this.cleanupRetryTimer !== void 0) {
|
|
252
278
|
return;
|
|
253
279
|
}
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
280
|
+
this.cleanupRetryTimer = setTimeout(() => {
|
|
281
|
+
this.cleanupRetryTimer = void 0;
|
|
282
|
+
void this.tryFinalizeCleanup();
|
|
283
|
+
}, CLEANUP_RETRY_INTERVAL_MS);
|
|
284
|
+
}
|
|
285
|
+
async tryFinalizeCleanup() {
|
|
286
|
+
if (this.cleanupInProgress) {
|
|
287
|
+
this.scheduleCleanupRetry();
|
|
288
|
+
return;
|
|
258
289
|
}
|
|
290
|
+
this.cleanupInProgress = true;
|
|
259
291
|
try {
|
|
260
292
|
if (this.connectionId) {
|
|
261
|
-
|
|
293
|
+
let closed = false;
|
|
294
|
+
try {
|
|
295
|
+
closed = await new Promise((resolvePromise, rejectPromise) => {
|
|
296
|
+
this.lib.connectionClose.async(
|
|
297
|
+
this.connectionId,
|
|
298
|
+
(error, result) => {
|
|
299
|
+
if (error) {
|
|
300
|
+
rejectPromise(error);
|
|
301
|
+
} else {
|
|
302
|
+
resolvePromise(result);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.error(
|
|
309
|
+
`Failed to close in-process FFI connection: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
310
|
+
);
|
|
311
|
+
FfiRuntimeHost.quarantinedHosts.add(this);
|
|
312
|
+
if (this.keepAliveTimer !== void 0) {
|
|
313
|
+
clearInterval(this.keepAliveTimer);
|
|
314
|
+
this.keepAliveTimer = void 0;
|
|
315
|
+
}
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (!closed) {
|
|
319
|
+
this.scheduleCleanupRetry();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
262
322
|
this.connectionId = 0;
|
|
263
323
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
324
|
+
const callbackUnregistered = this.unregisterCallback();
|
|
325
|
+
if (this.keepAliveTimer !== void 0) {
|
|
326
|
+
clearInterval(this.keepAliveTimer);
|
|
327
|
+
this.keepAliveTimer = void 0;
|
|
328
|
+
}
|
|
267
329
|
if (this.serverId) {
|
|
268
|
-
|
|
330
|
+
try {
|
|
331
|
+
if (!this.lib.hostShutdown(this.serverId)) {
|
|
332
|
+
console.error(
|
|
333
|
+
`In-process FFI host shutdown did not recognize server ${this.serverId}.`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error(
|
|
338
|
+
`Failed to shut down in-process FFI host: ${error instanceof Error ? error.stack ?? error.message : String(error)}`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
269
341
|
this.serverId = 0;
|
|
270
342
|
}
|
|
271
|
-
|
|
343
|
+
if (callbackUnregistered) {
|
|
344
|
+
FfiRuntimeHost.quarantinedHosts.delete(this);
|
|
345
|
+
}
|
|
346
|
+
} finally {
|
|
347
|
+
this.cleanupInProgress = false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** Awaits the initial cleanup attempt; a non-quiescent close is retried in the background. */
|
|
351
|
+
async dispose() {
|
|
352
|
+
if (this.disposed) {
|
|
353
|
+
return;
|
|
272
354
|
}
|
|
355
|
+
this.disposed = true;
|
|
273
356
|
this.receiveStream.end();
|
|
274
|
-
this.
|
|
357
|
+
if (!this.starting) {
|
|
358
|
+
await this.tryFinalizeCleanup();
|
|
359
|
+
}
|
|
275
360
|
}
|
|
276
361
|
}
|
|
277
362
|
// Annotate the CommonJS export names for ESM import in node:
|