fix: copilot SDK cleanup and TypeScript errors
This commit is contained in:
parent
d2b732487b
commit
59d383f7b6
@ -127,15 +127,6 @@ export async function runCopilotCliAgent(params: {
|
|||||||
systemPrompt,
|
systemPrompt,
|
||||||
timeoutMs: params.timeoutMs,
|
timeoutMs: params.timeoutMs,
|
||||||
sessionId: params.cliSessionId,
|
sessionId: params.cliSessionId,
|
||||||
onEvent: (event) => {
|
|
||||||
// Forward streaming events if streamParams is provided
|
|
||||||
if (params.streamParams?.onDelta && event.type === "assistant.message_delta") {
|
|
||||||
const data = event.data as { content?: string };
|
|
||||||
if (typeof data.content === "string") {
|
|
||||||
params.streamParams.onDelta(data.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const text = result.text?.trim();
|
const text = result.text?.trim();
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export async function createCopilotClient(
|
|||||||
cliPath: options?.cliPath ?? "copilot",
|
cliPath: options?.cliPath ?? "copilot",
|
||||||
cwd: options?.cwd,
|
cwd: options?.cwd,
|
||||||
logLevel: options?.logLevel ?? "warning",
|
logLevel: options?.logLevel ?? "warning",
|
||||||
autoRestart: options?.autoRestart ?? true,
|
autoRestart: false, // Disable auto-restart to avoid keeping event loop alive
|
||||||
useStdio: true, // Use stdio transport for better process control
|
useStdio: true, // Use stdio transport for better process control
|
||||||
autoStart: false, // We'll start manually for better error handling
|
autoStart: false, // We'll start manually for better error handling
|
||||||
env: options?.env,
|
env: options?.env,
|
||||||
@ -223,22 +223,68 @@ export async function runCopilotAgent(params: RunCopilotAgentParams): Promise<Co
|
|||||||
durationMs: Date.now() - started,
|
durationMs: Date.now() - started,
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up in reverse order: unsubscribe, destroy session (if new), stop client
|
// Clean up in order: unsubscribe, abort session, destroy session, stop client
|
||||||
|
// NOTE: Due to a limitation in vscode-jsonrpc (used by @github/copilot-sdk),
|
||||||
|
// the process may not exit cleanly after cleanup. This is acceptable for gateway
|
||||||
|
// usage but means CLI one-off commands will hang. The SDK team should fix this.
|
||||||
if (unsubscribe) {
|
if (unsubscribe) {
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only destroy session if we created a new one (not resuming)
|
// Abort any in-flight request, then destroy the session
|
||||||
if (session && !params.sessionId) {
|
if (session) {
|
||||||
await session.destroy().catch(() => {
|
try {
|
||||||
// Ignore cleanup errors
|
await session.abort();
|
||||||
});
|
} catch {
|
||||||
|
// Ignore abort errors (may not have active request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only destroy session if we created a new one (not resuming)
|
||||||
|
if (!params.sessionId) {
|
||||||
|
try {
|
||||||
|
await session.destroy();
|
||||||
|
} catch {
|
||||||
|
// Ignore destroy errors
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always stop the client
|
// Access internal SDK handles BEFORE cleanup so we can unref them after
|
||||||
await client.stop().catch(() => {
|
const clientAny = client as unknown as {
|
||||||
// Ignore cleanup errors
|
cliProcess?: {
|
||||||
});
|
unref?: () => void;
|
||||||
|
stdin?: { unref?: () => void };
|
||||||
|
stdout?: { unref?: () => void };
|
||||||
|
stderr?: { unref?: () => void };
|
||||||
|
removeAllListeners?: () => void;
|
||||||
|
};
|
||||||
|
socket?: { unref?: () => void };
|
||||||
|
};
|
||||||
|
const cliProcess = clientAny.cliProcess;
|
||||||
|
const socket = clientAny.socket;
|
||||||
|
|
||||||
|
// Stop the client gracefully first, then force if needed
|
||||||
|
try {
|
||||||
|
await client.stop();
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
await client.forceStop();
|
||||||
|
} catch {
|
||||||
|
// Ignore forceStop errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unref all handles to allow Node to exit (works around SDK cleanup bug)
|
||||||
|
if (cliProcess) {
|
||||||
|
cliProcess.unref?.();
|
||||||
|
cliProcess.stdin?.unref?.();
|
||||||
|
cliProcess.stdout?.unref?.();
|
||||||
|
cliProcess.stderr?.unref?.();
|
||||||
|
cliProcess.removeAllListeners?.();
|
||||||
|
}
|
||||||
|
if (socket) {
|
||||||
|
socket.unref?.();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +294,7 @@ export async function runCopilotAgent(params: RunCopilotAgentParams): Promise<Co
|
|||||||
export async function listCopilotSessions(options?: {
|
export async function listCopilotSessions(options?: {
|
||||||
cliPath?: string;
|
cliPath?: string;
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
}): Promise<Array<{ sessionId: string; model?: string; createdAt?: string }>> {
|
}): Promise<Array<{ sessionId: string; createdAt?: string }>> {
|
||||||
const client = await createCopilotClient({
|
const client = await createCopilotClient({
|
||||||
cliPath: options?.cliPath,
|
cliPath: options?.cliPath,
|
||||||
cwd: options?.cwd,
|
cwd: options?.cwd,
|
||||||
@ -259,11 +305,14 @@ export async function listCopilotSessions(options?: {
|
|||||||
const sessions = await client.listSessions();
|
const sessions = await client.listSessions();
|
||||||
return sessions.map((s) => ({
|
return sessions.map((s) => ({
|
||||||
sessionId: s.sessionId,
|
sessionId: s.sessionId,
|
||||||
model: s.model,
|
createdAt: s.startTime?.toISOString(),
|
||||||
createdAt: s.createdAt,
|
|
||||||
}));
|
}));
|
||||||
} finally {
|
} finally {
|
||||||
await client.stop().catch(() => {});
|
try {
|
||||||
|
await client.stop();
|
||||||
|
} catch {
|
||||||
|
// Ignore cleanup errors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +336,10 @@ export async function deleteCopilotSession(
|
|||||||
await client.deleteSession(sessionId);
|
await client.deleteSession(sessionId);
|
||||||
log.info("deleted copilot session", { sessionId });
|
log.info("deleted copilot session", { sessionId });
|
||||||
} finally {
|
} finally {
|
||||||
await client.stop().catch(() => {});
|
try {
|
||||||
|
await client.stop();
|
||||||
|
} catch {
|
||||||
|
// Ignore cleanup errors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user